From 8ccaf4cfe06c8a076175e53ac4fb69b3f0be523d Mon Sep 17 00:00:00 2001 From: Joel Pedraza Date: Mon, 3 Feb 2014 12:06:30 -0500 Subject: [PATCH 01/95] fix bug that caused all plugins to be activated twice on startup --- server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server.py b/server.py index cf45096..cb0389e 100644 --- a/server.py +++ b/server.py @@ -537,7 +537,6 @@ def __init__(self): except FatalPluginError: logger.critical("Shutting Down.") sys.exit() - self.plugin_manager.activate_plugins() self.reaper = LoopingCall(self.reap_dead_protocols) self.reaper.start(self.config.reap_time) logger.debug("Factory created, endpoint of port %d" % self.config.bind_port) From 7d7bd6a16298766c15490e8c9c7f0d43c0265fc3 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Mon, 3 Feb 2014 16:39:04 -0600 Subject: [PATCH 02/95] Added way better file path support. Should make testing easier, as well as allowing you to run it anywhere else. --- config.py | 51 +++++++++++-------- .../starbound_config_manager.py | 10 ++-- utility_functions.py | 6 ++- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/config.py b/config.py index 7a3aa59..aeb44b4 100644 --- a/config.py +++ b/config.py @@ -3,7 +3,7 @@ import logging import inspect import sys -from utility_functions import recursive_dictionary_update +from utility_functions import recursive_dictionary_update, path class Singleton(type): @@ -21,23 +21,31 @@ class ConfigurationManager(object): logger = logging.getLogger("starrypy.config.ConfigurationManager") def __init__(self): - try: - with open("config/config.json.default", "r") as default_config: - default = json.load(default_config) - except IOError: + default_config_path = path.preauthChild("config/config.json.default") + self.config_path = path.preauthChild("config/config.json") + if default_config_path.exists(): + try: + with default_config_path.open() as default_config: + default = json.load(default_config) + except ValueError: + self.logger.critical("The configuration defaults file (config.json.default) contains invalid JSON. Please run it against a JSON linter, such as http://jsonlint.com. Shutting down." ) + sys.exit() + else: self.logger.critical("The configuration defaults file (config.json.default) doesn't exist! Shutting down.") sys.exit() - except ValueError: - self.logger.critical("The configuration defaults file (config.json.default) contains invalid JSON. Please run it against a JSON linter, such as http://jsonlint.com. Shutting down." ) - sys.exit() - try: - with open("config/config.json", "r") as c: - config = json.load(c) - self.config = recursive_dictionary_update(default, config) - except IOError: + + if self.config_path.exists(): + try: + with self.config_path.open() as c: + config = json.load(c) + self.config = recursive_dictionary_update(default, config) + except ValueError: + self.logger.critical("The configuration file (config.json) contains invalid JSON. Please run it against a JSON linter, such as http://jsonlint.com. Shutting down.") + sys.exit() + else: self.logger.warning("The configuration file (config.json) doesn't exist! Creating one from defaults.") try: - with open("config/config.json", "w") as f: + with self.config_path.open("w") as f: json.dump(default, f, indent=4, separators=(',', ': '), sort_keys=True, ensure_ascii = False) except IOError: self.logger.critical("Couldn't write a default configuration file. Please check that StarryPy has write access in the config/ directory.") @@ -45,24 +53,21 @@ def __init__(self): sys.exit() self.logger.warning("StarryPy will now exit. Please examine config.json and adjust the variables appropriately.") sys.exit() - except ValueError: - self.logger.critical("The configuration file (config.json) contains invalid JSON. Please run it against a JSON linter, such as http://jsonlint.com. Shutting down.") - sys.exit() self.logger.debug("Created configuration manager.") self.save() def save(self): try: - with io.open("config/config.json", "w", encoding="utf-8") as config: + with io.open(self.config_path.path, "w", encoding="utf-8") as config: self.logger.debug("Writing configuration file.") - config.write(json.dumps(self.config, indent=4, separators=(',', ': '), sort_keys=True, ensure_ascii = False)) + config.write(json.dumps(self.config, indent=4, separators=(',', ': '), sort_keys=True, ensure_ascii=False)) except Exception as e: self.logger.critical("Tried to save the configuration file, failed.\n%s", str(e)) raise def __getattr__(self, item): - if item == "config": + if item in ["config", "config_path"]: return super(ConfigurationManager, self).__getattribute__(item) @@ -84,9 +89,13 @@ def __getattr__(self, item): def __setattr__(self, key, value): if key == "config": super(ConfigurationManager, self).__setattr__(key, value) + self.save() + elif key == "config_path": + super(ConfigurationManager, self).__setattr__(key, value) elif key == "plugin_config": caller = inspect.stack()[1][0].f_locals["self"].__class__.name self.config["plugin_config"][caller] = value + self.save else: self.config[key] = value - self.save() \ No newline at end of file + self.save() \ No newline at end of file diff --git a/plugins/core/starbound_config_manager/starbound_config_manager.py b/plugins/core/starbound_config_manager/starbound_config_manager.py index 0c2bb34..b1e7066 100644 --- a/plugins/core/starbound_config_manager/starbound_config_manager.py +++ b/plugins/core/starbound_config_manager/starbound_config_manager.py @@ -1,5 +1,5 @@ import json -import os +from twisted.python.filepath import FilePath from base_plugin import SimpleCommandPlugin from plugin_manager import FatalPluginError from plugins.core import permissions, UserLevels @@ -13,14 +13,14 @@ class StarboundConfigManager(SimpleCommandPlugin): def activate(self): super(StarboundConfigManager, self).activate() try: - configuration_file = os.path.join(self.config.starbound_path, "starbound.config") - if not os.path.exists(configuration_file): + configuration_file = FilePath(self.config.starbound_path).child('starbound.config') + if not configuration_file.exists(): raise FatalPluginError( "Could not open starbound configuration file. Tried path: %s" % configuration_file) except AttributeError: raise FatalPluginError("The starbound path (starbound_path) is not set in the configuration.") try: - with open(configuration_file, "r") as f: + with configuration_file.open() as f: starbound_config = json.load(f) except Exception as e: raise FatalPluginError( @@ -36,4 +36,4 @@ def activate(self): def spawn(self, data): """Moves your ship to spawn. Syntax: /move_ship_to_spawn""" self.plugins['warpy_plugin'].move_player_ship(self.protocol, [x for x in self._spawn]) - self.protocol.send_chat_message("Moving your ship to spawn.") + self.protocol.send_chat_message("Moving your ship to spawn.") \ No newline at end of file diff --git a/utility_functions.py b/utility_functions.py index 4b03807..a28da38 100644 --- a/utility_functions.py +++ b/utility_functions.py @@ -1,11 +1,14 @@ import collections import logging +import os from construct import Container +from twisted.python.filepath import FilePath import packets +path = FilePath(os.path.dirname(os.path.abspath(__file__))) logger = logging.getLogger("starrypy.utility_functions") @@ -85,4 +88,5 @@ def extract_name(l): else: name.append(s) raise ValueError("Final terminator character of <%s> not found" % - terminator) \ No newline at end of file + terminator) + From 0d81707255b55cb289cf11336e465f8e4096af5d Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Mon, 3 Feb 2014 17:38:41 -0600 Subject: [PATCH 03/95] Fixed paths everywhere; you can now run it without having to cd to the StarryPy directory itself. --- plugin_manager.py | 18 +++++++++--------- plugins/core/player_manager/manager.py | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugin_manager.py b/plugin_manager.py index 86c4893..4643d3d 100644 --- a/plugin_manager.py +++ b/plugin_manager.py @@ -4,14 +4,13 @@ """ import inspect import logging -import os import sys from twisted.internet import reactor from twisted.internet.task import deferLater from base_plugin import BasePlugin from config import ConfigurationManager - +from utility_functions import path class DuplicatePluginError(Exception): """ @@ -55,8 +54,9 @@ def __init__(self, factory, base_class=BasePlugin): self.base_class = base_class self.factory = factory self.load_order = [] - self.plugin_dir = os.path.realpath(self.config.plugin_path) - sys.path.append(self.plugin_dir) + #self.plugin_dir = os.path.realpath(self.config.plugin_path) + self.plugin_dir = path.child(self.config.plugin_path) + sys.path.append(self.plugin_dir.path) self.load_plugins(self.plugin_dir) self.logger.info("Loaded plugins:\n%s" % "\n".join( @@ -71,11 +71,11 @@ def load_plugins(self, plugin_dir): :return: None """ seen_plugins = [] - for f in os.listdir(plugin_dir): - if f.endswith(".py"): - name = f[:-3] - elif os.path.isdir(os.path.join(plugin_dir, f)): - name = f + for f in plugin_dir.globChildren("*"): + if f.splitext()[1] == ".py": + name = f.basename()[:-3] + elif f.isdir(): + name = f.basename() else: continue try: diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 990759f..f3bcc3d 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -11,7 +11,7 @@ from sqlalchemy.ext.declarative import declarative_base as sqla_declarative_base from twisted.words.ewords import AlreadyLoggedIn from sqlalchemy.types import TypeDecorator, VARCHAR - +from utility_functions import path class JSONEncodedDict(TypeDecorator): impl = VARCHAR @@ -159,7 +159,7 @@ class Ban(Base): class PlayerManager(object): def __init__(self, config): self.config = config - self.engine = create_engine('sqlite:///%s' % self.config.player_db) + self.engine = create_engine('sqlite:///%s' % path.preauthChild(self.config.player_db).path) self.session = Session(self.engine) Base.metadata.create_all(self.engine) for player in self.session.query(Player).all(): From 4982efbda2d34ff0580e797f2afb195a08d4eb1c Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Mon, 3 Feb 2014 20:45:21 -0600 Subject: [PATCH 04/95] Fixed error message on some log-ins because of the bouncer. --- plugins/bouncer_plugin/bouncer_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/bouncer_plugin/bouncer_plugin.py b/plugins/bouncer_plugin/bouncer_plugin.py index 43119b1..8bc3b47 100644 --- a/plugins/bouncer_plugin/bouncer_plugin.py +++ b/plugins/bouncer_plugin/bouncer_plugin.py @@ -28,6 +28,6 @@ def activate(self): (lambda x: False if self.protocol.player.access_level < UserLevels.REGISTERED else True)) def after_connect_response(self, data): - if self.protocol.player.access_level < UserLevels.REGISTERED: + if self.protocol.player is not None and self.protocol.player.access_level < UserLevels.REGISTERED: self.protocol.send_chat_message( "^#FF0000;This server is protected. You can't build or perform any destructive actions. Speak to an administrator about becoming a registered user.^#F7EB43;") \ No newline at end of file From 2a48082c8dceb13a93ce1533655f4f4f282ff853 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Mon, 3 Feb 2014 20:53:55 -0600 Subject: [PATCH 05/95] Fixed connection logging and added a few other checks to reduce chances of unnecessary exceptions. Shortened after_ callback time from 1 second to .01 second, may move it to immediate. --- plugin_manager.py | 2 +- plugins/announcer_plugin/announcer_plugin.py | 2 +- .../admin_command_plugin.py | 2 +- plugins/core/player_manager/plugin.py | 29 ++++++------ .../new_player_greeter_plugin.py | 15 +++---- server.py | 44 +++++++------------ 6 files changed, 39 insertions(+), 55 deletions(-) diff --git a/plugin_manager.py b/plugin_manager.py index 4643d3d..d33b017 100644 --- a/plugin_manager.py +++ b/plugin_manager.py @@ -208,7 +208,7 @@ def wrapped_function(self, data): res = self.plugin_manager.do(self, on, data) if res: res = func(self, data) - d = deferLater(reactor, 1, self.plugin_manager.do, self, after, data) + d = deferLater(reactor, .01, self.plugin_manager.do, self, after, data) d.addErrback(print_this_defered_failure) return res diff --git a/plugins/announcer_plugin/announcer_plugin.py b/plugins/announcer_plugin/announcer_plugin.py index b1ce7b3..136e0c8 100644 --- a/plugins/announcer_plugin/announcer_plugin.py +++ b/plugins/announcer_plugin/announcer_plugin.py @@ -23,7 +23,7 @@ def after_connect_response(self, data): return except: self.logger.exception("Unknown error in after_connect_response.", exc_info=True) - raise + return def on_client_disconnect(self, data): if self.protocol.player is not None: diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index fcf8af8..17399e9 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -152,7 +152,7 @@ def kick(self, data): info = self.player_manager.whois(name) if info and info.logged_in: tp = self.factory.protocols[info.protocol] - tp.die() + tp.loseConnection() self.factory.broadcast("%s kicked %s (reason: %s)" % (self.protocol.player.name, info.name, diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 1512e21..fbc789d 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -84,25 +84,26 @@ def after_connect_response(self, data): self.protocol.transport.getPeer().host)) def after_world_start(self, data): - world_start = packets.world_start().parse(data.data) - coords = world_start.planet['config']['coordinate'] - if coords is not None: - parent_system = coords['parentSystem'] - location = parent_system['location'] - l = location - self.protocol.player.on_ship = False - planet = Planet(parent_system['sector'], l[0], l[1], l[2], - coords['planetaryOrbitNumber'], coords['satelliteOrbitNumber']) - self.protocol.player.planet = str(planet) - self.logger.debug("Player %s is now at planet: %s", self.protocol.player.name, str(planet)) - else: - self.logger.info("Player %s is now on a ship.", self.protocol.player.name) - self.protocol.player.on_ship = True + world_start = packets.world_start().parse(data.data) + coords = world_start.planet['config']['coordinate'] + if coords is not None: + parent_system = coords['parentSystem'] + location = parent_system['location'] + l = location + self.protocol.player.on_ship = False + planet = Planet(parent_system['sector'], l[0], l[1], l[2], + coords['planetaryOrbitNumber'], coords['satelliteOrbitNumber']) + self.protocol.player.planet = str(planet) + self.logger.debug("Player %s is now at planet: %s", self.protocol.player.name, str(planet)) + else: + self.logger.info("Player %s is now on a ship.", self.protocol.player.name) + self.protocol.player.on_ship = True def on_client_disconnect(self, player): if self.protocol.player is not None and self.protocol.player.logged_in: self.logger.info("Player disconnected: %s", self.protocol.player.name) self.protocol.player.logged_in = False + return True @permissions(UserLevels.ADMIN) def delete_player(self, data): diff --git a/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py b/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py index 6579cb2..2c33183 100644 --- a/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py +++ b/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py @@ -13,16 +13,13 @@ def activate(self): super(NewPlayerGreeter, self).activate() def after_connect_response(self, data): - try: + if self.protocol.player is not None and self.protocol.player.logged_in: my_storage = self.protocol.player.storage - except AttributeError: - self.logger.debug("Tried to give item to non-existent protocol.") - return - if not 'given_starter_items' in my_storage or my_storage['given_starter_items'] == "False": - my_storage['given_starter_items'] = "True" - self.give_items() - self.send_greetings() - self.logger.info("Gave starter items to %s.", self.protocol.player.name) + if not 'given_starter_items' in my_storage or my_storage['given_starter_items'] == "False": + my_storage['given_starter_items'] = "True" + self.give_items() + self.send_greetings() + self.logger.info("Gave starter items to %s.", self.protocol.player.name) def give_items(self): for item in self.config.plugin_config["items"]: diff --git a/server.py b/server.py index cb0389e..1b5a518 100644 --- a/server.py +++ b/server.py @@ -96,6 +96,9 @@ def __init__(self): packets.Packets.HEARTBEAT: self.heartbeat, } self.client_protocol = None + self.packet_stream = PacketStream(self) + self.packet_stream.direction = packets.Direction.CLIENT + self.plugin_manager = self.factory.plugin_manager def connectionMade(self): """ @@ -106,9 +109,6 @@ def connectionMade(self): actual starbound server using StarboundClientFactory() :rtype : None """ - self.plugin_manager = self.factory.plugin_manager - self.packet_stream = PacketStream(self) - self.packet_stream.direction = packets.Direction.CLIENT logger.info("Connection established from IP: %s", self.transport.getPeer().host) reactor.connectTCP(self.config.upstream_hostname, self.config.upstream_port, StarboundClientFactory(self), timeout=self.config.server_connect_timeout) @@ -429,33 +429,16 @@ def connectionLost(self, reason=connectionDone): :param reason: The reason for the disconnection. :return: None """ + logger.info("Losing connection from IP: %s", self.transport.getPeer().host) + if self.player is not None: + self.player.logged_in = False + self.client_disconnect("") + if self.client_protocol is not None: + self.client_protocol.disconnect() try: - if self.client_protocol is not None: - x = build_packet(packets.Packets.CLIENT_DISCONNECT, - packets.client_disconnect().build(Container(data=0))) - if self.player is not None and self.player.logged_in: - self.client_disconnect(x) - self.player.protocol = None - self.player = None - self.client_protocol.transport.write(x) - self.client_protocol.transport.abortConnection() + self.factory.protocols.pop(self.id) except: - logger.error("Couldn't disconnect protocol.") - finally: - try: - self.factory.protocols.pop(self.id) - except: - self.logger.trace("Protocol was not in factory list. This should not happen.") - finally: - logger.info("Lost connection from IP: %s", self.transport.getPeer().host) - self.transport.abortConnection() - - def die(self): - self.connectionLost() - - def connectionFailed(self, *args, **kwargs): - self.connectionLost() - + self.logger.trace("Protocol was not in factory list. This should not happen.") class ClientProtocol(Protocol): """ @@ -476,7 +459,6 @@ def connectionMade(self): :return: None """ self.server_protocol.client_protocol = self - self.parsing = False def string_received(self, packet): @@ -517,6 +499,10 @@ def dataReceived(self, data): else: self.packet_stream += data + def disconnect(self): + x = build_packet(packets.Packets.CLIENT_DISCONNECT, packets.client_disconnect().build(Container(data=0))) + self.transport.write(x) + self.transport.abortConnection() class StarryPyServerFactory(ServerFactory): """ From d37fc19853816e935cfb92788a0322e5d466373a Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Mon, 3 Feb 2014 21:23:37 -0600 Subject: [PATCH 06/95] Fixed kick command --- .../admin_commands_plugin/admin_command_plugin.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 17399e9..7af8049 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -149,20 +149,24 @@ def kick(self, data): name, reason = extract_name(data) if reason is None: reason = "no reason given" + else: + reason = " ".join(reason) info = self.player_manager.whois(name) if info and info.logged_in: tp = self.factory.protocols[info.protocol] - tp.loseConnection() + tp.transport.loseConnection() self.factory.broadcast("%s kicked %s (reason: %s)" % (self.protocol.player.name, info.name, - " ".join(reason))) - self.logger.info("%s kicked %s (reason: %s", self.protocol.player.name, info.name, - " ".join(reason)) + reason)) + self.logger.info("%s kicked %s (reason: %s)", self.protocol.player.name, info.name, + reason) else: self.protocol.send_chat_message("Couldn't find a user by the name %s." % name) return False + + @permissions(UserLevels.ADMIN) def ban(self, data): """Bans an IP (retrieved by /whois). Syntax: /ban [ip address]""" From 0a809cf351847d774599ba12a1a5d67f3879fa46 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Mon, 3 Feb 2014 23:07:00 -0600 Subject: [PATCH 07/95] Removed all exc_info's for better pypy compatibility, and no longer stop on import error. --- packet_stream.py | 4 +-- packets/data_types.py | 9 +++---- plugin_manager.py | 4 +-- plugins/announcer_plugin/announcer_plugin.py | 2 +- .../admin_command_plugin.py | 2 +- plugins/core/command_plugin/command_plugin.py | 2 +- plugins/core/player_manager/plugin.py | 25 +++++++++++-------- plugins/motd_plugin/motd_plugin.py | 2 +- server.py | 4 +-- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packet_stream.py b/packet_stream.py index 9ee3db4..a460786 100644 --- a/packet_stream.py +++ b/packet_stream.py @@ -56,7 +56,7 @@ def start_packet(self): self.packet_size = self.payload_size + self.header_length return True except: - self.logger.exception("Unknown error in start_packet.", exc_info=True) + self.logger.exception("Unknown error in start_packet.") return False def check_packet(self): @@ -89,7 +89,7 @@ def check_packet(self): if self.start_packet(): self.check_packet() except: - self.logger.exception("Unknown error in check_packet", exc_info=True) + self.logger.exception("Unknown error in check_packet") def reset(self): self.id = None diff --git a/packets/data_types.py b/packets/data_types.py index 755f562..676301d 100644 --- a/packets/data_types.py +++ b/packets/data_types.py @@ -26,7 +26,7 @@ def _build(self, obj, stream, context): value -= 1 VLQ("")._build(value, stream, context) except: - self.logger.exception("Error building SignedVLQ.", exc_info=True) + self.logger.exception("Error building SignedVLQ.") raise @@ -73,11 +73,8 @@ def _decode(self, obj, context): class Joiner(Adapter): def _encode(self, obj, context): return obj - def _decode(self, obj, context): return "".join(obj) - - star_string_struct = lambda name="star_string": Struct(name, VLQ("length"), String("string", lambda ctx: ctx.length) @@ -121,6 +118,6 @@ class StarByteArray(Construct): def _parse(self, stream, context): l = VLQ("").parse_stream(stream) return _read_stream(stream, l) - def _build(self, obj, stream, context): - _write_stream(stream, len(obj), VLQ("").build(len(obj)) + obj) + _write_stream(stream, len(obj), VLQ("").build(len(obj))+obj) + diff --git a/plugin_manager.py b/plugin_manager.py index d33b017..eb278d8 100644 --- a/plugin_manager.py +++ b/plugin_manager.py @@ -93,7 +93,6 @@ def load_plugins(self, plugin_dir): except ImportError: self.logger.critical("Import error for %s", name) - sys.exit() try: dependencies = {x.name: set(x.depends) for x in seen_plugins} classes = {x.name: x for x in seen_plugins} @@ -171,8 +170,7 @@ def do(self, protocol, command, data): res = True return_values.append(res) except: - self.logger.exception("Error in plugin %s with function %s.", str(plugin), command, - exc_info=True) + self.logger.exception("Error in plugin %s with function %s.", str(plugin), command) return all(return_values) def get_by_name(self, name): diff --git a/plugins/announcer_plugin/announcer_plugin.py b/plugins/announcer_plugin/announcer_plugin.py index 136e0c8..f681ee8 100644 --- a/plugins/announcer_plugin/announcer_plugin.py +++ b/plugins/announcer_plugin/announcer_plugin.py @@ -22,7 +22,7 @@ def after_connect_response(self, data): self.logger.debug("Attribute error in after_connect_response.") return except: - self.logger.exception("Unknown error in after_connect_response.", exc_info=True) + self.logger.exception("Unknown error in after_connect_response.") return def on_client_disconnect(self, data): diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 7af8049..b5db436 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -172,7 +172,7 @@ def ban(self, data): """Bans an IP (retrieved by /whois). Syntax: /ban [ip address]""" try: ip = data[0] - socket.inet_aton(ip) + print socket.inet_aton(ip) self.logger.debug("Banning IP address %s" % ip) self.player_manager.ban(ip) self.protocol.send_chat_message("Banned IP: %s" % ip) diff --git a/plugins/core/command_plugin/command_plugin.py b/plugins/core/command_plugin/command_plugin.py index d5ac54b..4cdc725 100644 --- a/plugins/core/command_plugin/command_plugin.py +++ b/plugins/core/command_plugin/command_plugin.py @@ -24,7 +24,7 @@ def on_chat_sent(self, data): return True return False except: - self.logger.exception("Error in on_chat_sent.", exc_info=True) + self.logger.exception("Error in on_chat_sent.") raise def register(self, f, names): diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index fbc789d..41d3e51 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -72,16 +72,21 @@ def reject_with_reason(self, reason): self.protocol.transport.write(rejection) self.protocol.transport.loseConnection() - def after_connect_response(self, data): - connection_parameters = connect_response().parse(data.data) - if not connection_parameters.success: - self.protocol.transport.loseConnection() - else: - self.protocol.player.client_id = connection_parameters.client_id - self.protocol.player.logged_in = True - self.logger.info("Player %s (UUID: %s, IP: %s) logged in" % ( - self.protocol.player.name, self.protocol.player.uuid, - self.protocol.transport.getPeer().host)) + def on_connect_response(self, data): + try: + connection_parameters = connect_response().parse(data.data) + if not connection_parameters.success: + self.protocol.transport.loseConnection() + else: + self.protocol.player.client_id = connection_parameters.client_id + self.protocol.player.logged_in = True + self.logger.info("Player %s (UUID: %s, IP: %s) logged in" % ( + self.protocol.player.name, self.protocol.player.uuid, + self.protocol.transport.getPeer().host)) + except: + self.logger.exception("Exception in on_connect_response, player info may not have been logged.") + finally: + return True def after_world_start(self, data): world_start = packets.world_start().parse(data.data) diff --git a/plugins/motd_plugin/motd_plugin.py b/plugins/motd_plugin/motd_plugin.py index 94e6382..172b1b9 100644 --- a/plugins/motd_plugin/motd_plugin.py +++ b/plugins/motd_plugin/motd_plugin.py @@ -44,7 +44,7 @@ def set_motd(self, motd): self.logger.info("MOTD changed to: %s", self._motd) self.send_motd() except: - self.logger.exception("Couldn't change message of the day.", exc_info=True) + self.logger.exception("Couldn't change message of the day.") raise diff --git a/server.py b/server.py index 1b5a518..17ba507 100644 --- a/server.py +++ b/server.py @@ -478,7 +478,7 @@ def string_received(self, packet): packet): self.server_protocol.write(packet.original_data) except construct.core.FieldError: - logger.exception("Construct field error in string_received.", exc_info=True) + logger.exception("Construct field error in string_received.") self.server_protocol.write( packet.original_data) @@ -550,7 +550,7 @@ def broadcast(self, text, channel=1, world='', name=''): try: p.send_chat_message(text) except: - logger.exception("Exception in broadcast.", exc_info=True) + logger.exception("Exception in broadcast.") def buildProtocol(self, address): """ From 79c5abf6da6357443649aafa09ac8bb62e7ecb5c Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 4 Feb 2014 12:40:17 +0100 Subject: [PATCH 08/95] lets try this landscape.io out --- .landscape.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .landscape.yaml diff --git a/.landscape.yaml b/.landscape.yaml new file mode 100644 index 0000000..6a8d7d1 --- /dev/null +++ b/.landscape.yaml @@ -0,0 +1,4 @@ +doc-warnings: yes +test-warnings: no +strictness: high +autodetect: yes \ No newline at end of file From 65ed4165e0092e48a3547c2beb62c874dac3b3ae Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 4 Feb 2014 12:59:58 +0100 Subject: [PATCH 09/95] changes hardcoded ## to use chat_prefix --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index b5db436..b0b128e 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -293,9 +293,9 @@ class MuteManager(BasePlugin): def on_chat_sent(self, data): data = chat_sent().parse(data.data) if self.protocol.player.muted and data.message[0] != self.config.command_prefix and data.message[ - :2] != "##": + :2] != self.config.chat_prefix*2: self.protocol.send_chat_message( - "You are currently muted and cannot speak. You are limited to commands and admin chat (prefix your lines with ## for admin chat.") + "You are currently muted and cannot speak. You are limited to commands and admin chat (prefix your lines with %s for admin chat." % (self.config.chat_prefix*2)) return False return True From 4fbbde95f396d29d894136039549b38b7c67233a Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 4 Feb 2014 21:33:34 +0100 Subject: [PATCH 10/95] reworks the UDP proxy to be a plugin --- plugins/UDPForwarder/UDPForwarder.py | 32 ++++++++++++++++++++++++++++ plugins/UDPForwarder/__init__.py | 1 + server.py | 13 +---------- 3 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 plugins/UDPForwarder/UDPForwarder.py create mode 100644 plugins/UDPForwarder/__init__.py diff --git a/plugins/UDPForwarder/UDPForwarder.py b/plugins/UDPForwarder/UDPForwarder.py new file mode 100644 index 0000000..f766aec --- /dev/null +++ b/plugins/UDPForwarder/UDPForwarder.py @@ -0,0 +1,32 @@ +from twisted.internet import reactor +from twisted.internet.error import CannotListenError +from twisted.internet.protocol import DatagramProtocol + +from base_plugin import BasePlugin + + +class UDPForwader(BasePlugin): + """Forwards UDP datagrams to the gameserver, mostly used for Valve's Steam style statistis queries""" + name = "udp_forwarder" + auto_activate = True + + def activate(self): + + super(UDPForwader, self).activate() + try: + reactor.listenUDP(self.config.bind_port, UDPProxy(self.config.upstream_hostname, self.config.upstream_port)) + self.logger.info("Listening for UDP on port %d" % self.config.bind_port) + except CannotListenError: + self.logger.error( + "Could not listen on UDP port %d. Will continue running, but please note that steam statistics will be unavailable.", + self.factory.config.bind_port + ) + + +class UDPProxy(DatagramProtocol): + def __init__(self,upstream_hostname, upstream_port): + self.upstream_hostname = upstream_hostname + self.upstream_port = upstream_port + + def datagramReceived(self, datagram, addr): + self.transport.write(datagram, (self.upstream_hostname, self.upstream_port)) diff --git a/plugins/UDPForwarder/__init__.py b/plugins/UDPForwarder/__init__.py new file mode 100644 index 0000000..47aadc5 --- /dev/null +++ b/plugins/UDPForwarder/__init__.py @@ -0,0 +1 @@ +from UDPForwarder import UDPForwader diff --git a/server.py b/server.py index 17ba507..11c8f6b 100644 --- a/server.py +++ b/server.py @@ -9,7 +9,7 @@ import construct from twisted.internet import reactor from twisted.internet.error import CannotListenError -from twisted.internet.protocol import ClientFactory, ServerFactory, Protocol, connectionDone, DatagramProtocol +from twisted.internet.protocol import ClientFactory, ServerFactory, Protocol, connectionDone from construct import Container import construct.core from twisted.internet.task import LoopingCall @@ -602,11 +602,6 @@ def buildProtocol(self, address): protocol.server_protocol = self.server_protocol return protocol - -class UDPProxy(DatagramProtocol): - def datagramReceived(self, datagram, addr): - self.transport.write(datagram, (self.config.upstream_hostname, self.config.upstream_port)) - if __name__ == '__main__': logger = logging.getLogger('starrypy') logger.setLevel(9) @@ -658,10 +653,4 @@ def datagramReceived(self, datagram, addr): logger.critical("Cannot listen on TCP port %d. Exiting.", factory.config.bind_port) sys.exit() logger.info("Listening on port %s" % factory.config.bind_port) - try: - reactor.listenUDP(config.bind_port, UDPProxy()) - except CannotListenError: - logger.error( - "Could not listen on UDP port %d. Will continue running, but please note that steam statistics will be unavailable.", - factory.config.bind_port) reactor.run() From 969cc15786e70e8436c5be4182521fef6f39c196 Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 4 Feb 2014 21:58:27 +0100 Subject: [PATCH 11/95] makes use of datetime.utcnow() --- packet_stream.py | 4 ++-- plugins/core/player_manager/manager.py | 2 +- server.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packet_stream.py b/packet_stream.py index a460786..00151bc 100644 --- a/packet_stream.py +++ b/packet_stream.py @@ -29,7 +29,7 @@ def __init__(self, protocol): self.packet_size = None self.protocol = protocol self.direction = None - self.last_received_timestamp = datetime.datetime.now() + self.last_received_timestamp = datetime.datetime.utcnow() def __add__(self, other): self._stream += other @@ -39,7 +39,7 @@ def __add__(self, other): except: pass finally: - self.last_received_timestamp = datetime.datetime.now() + self.last_received_timestamp = datetime.datetime.utcnow() return self def start_packet(self): diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index f3bcc3d..1f288e0 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -186,7 +186,7 @@ def fetch_or_create(self, uuid, name, ip, protocol=None): else: logger.info("Adding new player with name: %s" % name) player = Player(uuid=uuid, name=name, - last_seen=datetime.datetime.now(), + last_seen=datetime.datetime.utcnow(), access_level=int(UserLevels.GUEST), logged_in=False, protocol=protocol, diff --git a/server.py b/server.py index 11c8f6b..4a067fe 100644 --- a/server.py +++ b/server.py @@ -565,7 +565,7 @@ def buildProtocol(self, address): def reap_dead_protocols(self): logger.debug("Reaping dead connections.") count = 0 - start_time = datetime.datetime.now() + start_time = datetime.datetime.utcnow() for protocol in self.protocols.itervalues(): if ( protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: From 3788f5944f90117eb0061703ff4b8619f660256b Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 4 Feb 2014 22:45:23 +0100 Subject: [PATCH 12/95] makes more things configurable - [x] back packet types - [x] protect everything --- config/config.json.default | 12 ++++++++++++ plugins/planet_protect/planet_protect_plugin.py | 15 ++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index eec15b2..c761ac5 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -57,6 +57,18 @@ }, "planet_protect": { "auto_activate": true, + "protect_everything": false, + "bad_packets": [ + "CONNECT_WIRE", + "DISCONNECT_ALL_WIRES", + "OPEN_CONTAINER", + "CLOSE_CONTAINER", + "SWAP_IN_CONTAINER", + "DAMAGE_TILE", + "DAMAGE_TILE_GROUP", + "REQUEST_DROP", + "MODIFY_TILE_LIST" + ], "blacklist": [ "bomb", "bombblockexplosion", diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index ca6b775..7981779 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -15,24 +15,17 @@ class PlanetProtectPlugin(SimpleCommandPlugin): def activate(self): super(PlanetProtectPlugin, self).activate() - bad_packets = [ - "CONNECT_WIRE", - "DISCONNECT_ALL_WIRES", - "OPEN_CONTAINER", - "CLOSE_CONTAINER", - "SWAP_IN_CONTAINER", - "DAMAGE_TILE", - "DAMAGE_TILE_GROUP", - "REQUEST_DROP", - "MODIFY_TILE_LIST"] + bad_packets = self.config.plugin_config.get("bad_packets", []) for n in ["on_" + n.lower() for n in bad_packets]: setattr(self, n, (lambda x: self.planet_check())) self.protected_planets = self.config.plugin_config.get("protected_planets", []) self.blacklist = self.config.plugin_config.get("blacklist", []) self.player_manager = self.plugins.get("player_manager", []) + self.protect_everything = self.config.plugin_config.get("protect_everything", []) def planet_check(self): - if not self.protocol.player.on_ship and self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.REGISTERED: + if self.protect_everything or ( + not self.protocol.player.on_ship and self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.REGISTERED): return False else: return True From 5b270a32349c3a15bca3c7cd6d86e6e51fcc3722 Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 4 Feb 2014 22:49:53 +0100 Subject: [PATCH 13/95] removes Bouncer plugin its functionality is now in planet_protect --- config/config.json.default | 3 --- plugins/bouncer_plugin/__init__.py | 1 - plugins/bouncer_plugin/bouncer_plugin.py | 33 ------------------------ 3 files changed, 37 deletions(-) delete mode 100644 plugins/bouncer_plugin/__init__.py delete mode 100644 plugins/bouncer_plugin/bouncer_plugin.py diff --git a/config/config.json.default b/config/config.json.default index c761ac5..35c11c9 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -25,9 +25,6 @@ "announcer_plugin": { "auto_activate": true }, - "bouncer": { - "auto_activate": false - }, "chat_logger": { "auto_activate": true }, diff --git a/plugins/bouncer_plugin/__init__.py b/plugins/bouncer_plugin/__init__.py deleted file mode 100644 index 516cfab..0000000 --- a/plugins/bouncer_plugin/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from bouncer_plugin import BouncerPlugin \ No newline at end of file diff --git a/plugins/bouncer_plugin/bouncer_plugin.py b/plugins/bouncer_plugin/bouncer_plugin.py deleted file mode 100644 index 8bc3b47..0000000 --- a/plugins/bouncer_plugin/bouncer_plugin.py +++ /dev/null @@ -1,33 +0,0 @@ -from base_plugin import BasePlugin -from plugins.core.player_manager import UserLevels - - -class BouncerPlugin(BasePlugin): - """ - Prohibits players with a UserLevel < REGISTRED from destructive actions. - """ - name = "bouncer" - auto_activate = False - - def activate(self): - super(BouncerPlugin, self).activate() - bad_packets = [ - "CONNECT_WIRE", - "DISCONNECT_ALL_WIRES", - "OPEN_CONTAINER", - "CLOSE_CONTAINER", - "SWAP_IN_CONTAINER", - "DAMAGE_TILE", - "DAMAGE_TILE_GROUP", - "REQUEST_DROP", - "ENTITY_INTERACT", - "MODIFY_TILE_LIST" - ] - for n in ["on_" + n.lower() for n in bad_packets]: - setattr(self, n, - (lambda x: False if self.protocol.player.access_level < UserLevels.REGISTERED else True)) - - def after_connect_response(self, data): - if self.protocol.player is not None and self.protocol.player.access_level < UserLevels.REGISTERED: - self.protocol.send_chat_message( - "^#FF0000;This server is protected. You can't build or perform any destructive actions. Speak to an administrator about becoming a registered user.^#F7EB43;") \ No newline at end of file From d29be381a2480477da93c9c4cf8f18d332e73a4f Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Wed, 5 Feb 2014 15:47:37 +0100 Subject: [PATCH 14/95] adds broadcast_planet method --- .../core/admin_commands_plugin/admin_command_plugin.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index b0b128e..17a69fe 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -13,7 +13,7 @@ class UserCommandPlugin(SimpleCommandPlugin): """ name = "user_management_commands" depends = ['command_dispatcher', 'player_manager'] - commands = ["who", "whois", "promote", "kick", "ban", "give_item", "planet", "mute", "unmute", + commands = ["me", "who", "whois", "promote", "kick", "ban", "give_item", "planet", "mute", "unmute", "passthrough", "shutdown"] auto_activate = True @@ -21,6 +21,13 @@ def activate(self): super(UserCommandPlugin, self).activate() self.player_manager = self.plugins['player_manager'].player_manager + @permissions(UserLevels.GUEST) + def me(self, data): + """Preforms a player emote. Syntax: /me """ + emote = " ".join(data) + self.factory.broadcast_planet("^#CCCCCC;%s %s" % (self.protocol.player.name, emote), planet=self.protocol.player.planet) + return False + @permissions(UserLevels.GUEST) def who(self, data): """Returns all current users on the server. Syntax: /who""" From 53cf0d162fe6329864c0d866dddc3b1762eeaa53 Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Wed, 5 Feb 2014 15:48:59 +0100 Subject: [PATCH 15/95] Revert "adds broadcast_planet method" This reverts commit d29be381a2480477da93c9c4cf8f18d332e73a4f. --- .../core/admin_commands_plugin/admin_command_plugin.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 17a69fe..b0b128e 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -13,7 +13,7 @@ class UserCommandPlugin(SimpleCommandPlugin): """ name = "user_management_commands" depends = ['command_dispatcher', 'player_manager'] - commands = ["me", "who", "whois", "promote", "kick", "ban", "give_item", "planet", "mute", "unmute", + commands = ["who", "whois", "promote", "kick", "ban", "give_item", "planet", "mute", "unmute", "passthrough", "shutdown"] auto_activate = True @@ -21,13 +21,6 @@ def activate(self): super(UserCommandPlugin, self).activate() self.player_manager = self.plugins['player_manager'].player_manager - @permissions(UserLevels.GUEST) - def me(self, data): - """Preforms a player emote. Syntax: /me """ - emote = " ".join(data) - self.factory.broadcast_planet("^#CCCCCC;%s %s" % (self.protocol.player.name, emote), planet=self.protocol.player.planet) - return False - @permissions(UserLevels.GUEST) def who(self, data): """Returns all current users on the server. Syntax: /who""" From a2ae07f5666e5c42b20bb7e41e6b5aea45493699 Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Wed, 5 Feb 2014 15:49:07 +0100 Subject: [PATCH 16/95] adds broadcast_planet --- server.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server.py b/server.py index 4a067fe..f918f58 100644 --- a/server.py +++ b/server.py @@ -552,6 +552,24 @@ def broadcast(self, text, channel=1, world='', name=''): except: logger.exception("Exception in broadcast.") + def broadcast_planet(self, text, planet, name=''): + """ + Convenience method to send a broadcasted message to all clients on the + current planet (and ships orbiting it). + + :param text: Message text + :param planet: The planet to send the message to + :param name: The name to prepend before the message, format is , not prepanded when empty + :return: None + """ + for p in self.protocols.itervalues(): + if p.player.planet == planet: + try: + p.send_chat_message(text) + except: + logger.exception("Exception in broadcast.") + + def buildProtocol(self, address): """ Builds the protocol to a given address. From 0ac825d2c92246843cae205e9c5d4cd7eef3370d Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Mon, 10 Feb 2014 12:09:23 +0100 Subject: [PATCH 17/95] adds config param to set address to listen on --- config/config.json.default | 1 + plugins/UDPForwarder/UDPForwarder.py | 2 +- server.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 35c11c9..0e4788b 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -1,5 +1,6 @@ { "bind_port": 21025, + "bind_address": "", "chat_prefix": "@", "colors": { "admin": "^#C443F7;", diff --git a/plugins/UDPForwarder/UDPForwarder.py b/plugins/UDPForwarder/UDPForwarder.py index f766aec..c02579d 100644 --- a/plugins/UDPForwarder/UDPForwarder.py +++ b/plugins/UDPForwarder/UDPForwarder.py @@ -14,7 +14,7 @@ def activate(self): super(UDPForwader, self).activate() try: - reactor.listenUDP(self.config.bind_port, UDPProxy(self.config.upstream_hostname, self.config.upstream_port)) + reactor.listenUDP(self.config.bind_port, UDPProxy(self.config.upstream_hostname, self.config.upstream_port), interface=self.config.bind_address) self.logger.info("Listening for UDP on port %d" % self.config.bind_port) except CannotListenError: self.logger.error( diff --git a/server.py b/server.py index f918f58..3a09ea3 100644 --- a/server.py +++ b/server.py @@ -666,7 +666,7 @@ def buildProtocol(self, address): factory = StarryPyServerFactory() logger.debug("Attempting to listen on TCP port %d", factory.config.bind_port) try: - reactor.listenTCP(factory.config.bind_port, factory) + reactor.listenTCP(factory.config.bind_port, factory, interface=factory.config.bind_address) except CannotListenError: logger.critical("Cannot listen on TCP port %d. Exiting.", factory.config.bind_port) sys.exit() From 3f12b6737e18116cf9b51d2f1d472edb7254eb7c Mon Sep 17 00:00:00 2001 From: slitherrr Date: Mon, 10 Feb 2014 09:01:48 -0800 Subject: [PATCH 18/95] Some SQLAlchemy session cleanup Rebuilt #93 on development, then split out the plugin part. This is the session handling cleanup. The point is to abstract any session management away from the endpoints are using the data, and to initiate a session per transaction rather than leaving one session open for the lifetime of the server (the latter was causing concurrency issues when different factories were accessing the session). --- base_plugin.py | 7 +- plugin_manager.py | 4 +- .../admin_command_plugin.py | 22 +- plugins/core/colored_names/colored_names.py | 1 - plugins/core/player_manager/manager.py | 222 +++++++++++++----- plugins/core/player_manager/plugin.py | 14 +- .../planet_protect/planet_protect_plugin.py | 2 +- server.py | 38 ++- 8 files changed, 209 insertions(+), 101 deletions(-) diff --git a/base_plugin.py b/base_plugin.py index c6f9401..2ca7153 100644 --- a/base_plugin.py +++ b/base_plugin.py @@ -3,11 +3,11 @@ class BasePlugin(object): Defines an interface for all plugins to inherit from. Note that the __init__ method should generally not be overrode; all setup work should be done in activate() if possible. If you do override __init__, remember to super()! - + Note that only one instance of each plugin will be instantiated for *all* connected clients. self.protocol will be changed by the plugin manager to the current protocol. - + You may access the factory if necessary via self.factory.protocols to access other clients, but this "Is Not A Very Good Idea" (tm) @@ -357,8 +357,7 @@ def activate(self): for alias in alias_list: self.plugins['command_dispatcher'].register(alias, command) - def deactivate(self): super(SimpleCommandPlugin, self).deactivate() for command in self.commands: - self.plugins['command_dispatcher'].unregister(command) \ No newline at end of file + self.plugins['command_dispatcher'].unregister(command) diff --git a/plugin_manager.py b/plugin_manager.py index eb278d8..d55dc74 100644 --- a/plugin_manager.py +++ b/plugin_manager.py @@ -119,7 +119,6 @@ def load_plugins(self, plugin_dir): self.logger.critical(str(e)) self.activate_plugins() - def reload_plugins(self): self.logger.warning("Reloading plugins.") for x in self.plugins: @@ -132,7 +131,6 @@ def reload_plugins(self): self.logger.exception("Couldn't reload plugins!") raise - def activate_plugins(self): for plugin in [self.plugins[x] for x in self.load_order]: if self.config.config['plugin_config'][plugin.name]['auto_activate']: @@ -217,4 +215,4 @@ def print_this_defered_failure(f): class FatalPluginError(Exception): - pass \ No newline at end of file + pass diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index b0b128e..a8dfe03 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -107,41 +107,21 @@ def promote(self, data): def make_guest(self, player): self.logger.trace("Setting %s to GUEST", player.name) player.access_level = UserLevels.GUEST - try: - self.player_manager.session.commit() - except: - self.player_manager.session.rollback() - raise @permissions(UserLevels.MODERATOR) def make_registered(self, player): self.logger.trace("Setting %s to REGISTERED", player.name) player.access_level = UserLevels.REGISTERED - try: - self.player_manager.session.commit() - except: - self.player_manager.session.rollback() - raise @permissions(UserLevels.ADMIN) def make_mod(self, player): player.access_level = UserLevels.MODERATOR self.logger.trace("Setting %s to MODERATOR", player.name) - try: - self.player_manager.session.commit() - except: - self.player_manager.session.rollback() - raise @permissions(UserLevels.OWNER) def make_admin(self, player): self.logger.trace("Setting %s to ADMIN", player.name) player.access_level = UserLevels.ADMIN - try: - self.player_manager.session.commit() - except: - self.player_manager.session.rollback() - raise @permissions(UserLevels.MODERATOR) def kick(self, data): @@ -198,7 +178,7 @@ def unban(self, data): ip = data[0] for ban in self.player_manager.bans: if ban.ip == ip: - self.player_manager.session.delete(ban) + self.player_manager.remove_ban(ban) self.protocol.send_chat_message("Unbanned IP: %s" % ip) break else: diff --git a/plugins/core/colored_names/colored_names.py b/plugins/core/colored_names/colored_names.py index 1ed9721..d9df066 100644 --- a/plugins/core/colored_names/colored_names.py +++ b/plugins/core/colored_names/colored_names.py @@ -27,4 +27,3 @@ def on_chat_received(self, data): self.logger.warning("Received AttributeError in colored_name. %s", str(e)) self.protocol.transport.write(data.original_data) return False - diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 1f288e0..a86c680 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -1,3 +1,4 @@ +from contextlib import contextmanager import datetime from functools import wraps import inspect @@ -6,13 +7,29 @@ from enum import Enum from sqlalchemy.ext.mutable import Mutable -from sqlalchemy.orm import Session, relationship, backref +from sqlalchemy.orm import sessionmaker, relationship, backref from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKey, Boolean, func from sqlalchemy.ext.declarative import declarative_base as sqla_declarative_base from twisted.words.ewords import AlreadyLoggedIn from sqlalchemy.types import TypeDecorator, VARCHAR from utility_functions import path + +@contextmanager +def _autoclosing_session(sm): + session = sm() + + try: + yield session + + except: + session.rollback() + raise + + finally: + session.close() + + class JSONEncodedDict(TypeDecorator): impl = VARCHAR @@ -91,6 +108,32 @@ def __delitem__(self, key): MutableDict.associate_with(JSONEncodedDict) +class RecordWithAttachedSession(object): + def __init__(self, record, sessionmaker): + self.__dict__['record'] = record + self.__dict__['sessionmaker'] = sessionmaker + + def __getattr__(self, name): + with _autoclosing_session(self.sessionmaker) as session: + if sessionmaker.object_session(self.record) != session: + session.add(self.record) + session.refresh(self.record) + val = getattr(self.record, name) + + return val + + def __setattr__(self, name, val): + with _autoclosing_session(self.sessionmaker) as session: + if sessionmaker.object_session(self.record) != session: + session.add(self.record) + session.refresh(self.record) + setattr(self.record, name, val) + session.merge(self.record) + session.commit() + + return val + + class Player(Base): __tablename__ = 'players' @@ -160,75 +203,144 @@ class PlayerManager(object): def __init__(self, config): self.config = config self.engine = create_engine('sqlite:///%s' % path.preauthChild(self.config.player_db).path) - self.session = Session(self.engine) Base.metadata.create_all(self.engine) - for player in self.session.query(Player).all(): - player.logged_in = False - player.protocol = None + self.sessionmaker = sessionmaker(bind=self.engine, autoflush=True) + with _autoclosing_session(self.sessionmaker) as session: + for player in session.query(Player).all(): + player.logged_in = False + player.protocol = None + session.commit() + + def _cache_and_return_from_session(self, session, record, collection=False): + to_return = record + + if not isinstance(record, Base): + return to_return + + if collection: + to_return = [] + for r in record: + to_return.append(RecordWithAttachedSession(r, self.sessionmaker)) + else: + to_return = RecordWithAttachedSession(record, self.sessionmaker) + + return to_return def fetch_or_create(self, uuid, name, ip, protocol=None): - if self.session.query(Player).filter_by(uuid=uuid, logged_in=True).first(): - raise AlreadyLoggedIn - if self.check_bans(ip): - raise Banned - while self.whois(name): - logger.info("Got a duplicate player, affixing _ to name") - name += "_" - player = self.session.query(Player).filter_by(uuid=uuid).first() - if player: - if player.name != name: - logger.info("Detected username change.") - player.name = name - if ip not in player.ips: - player.ips.append(IPAddress(ip=ip)) - player.ip = ip - player.protocol = protocol - else: - logger.info("Adding new player with name: %s" % name) - player = Player(uuid=uuid, name=name, - last_seen=datetime.datetime.utcnow(), - access_level=int(UserLevels.GUEST), - logged_in=False, - protocol=protocol, - client_id=-1, - ip=ip, - planet="", - on_ship=True) - player.ips = [IPAddress(ip=ip)] - self.session.add(player) - if uuid == self.config.owner_uuid: - player.access_level = int(UserLevels.OWNER) - try: - self.session.commit() - except: - self.session.rollback() - raise - return player + with _autoclosing_session(self.sessionmaker) as session: + if session.query(Player).filter_by(uuid=uuid, logged_in=True).first(): + raise AlreadyLoggedIn + if self.check_bans(ip): + raise Banned + while self.whois(name): + logger.info("Got a duplicate player, affixing _ to name") + name += "_" + player = session.query(Player).filter_by(uuid=uuid).first() + if player: + if player.name != name: + logger.info("Detected username change.") + player.name = name + if ip not in player.ips: + player.ips.append(IPAddress(ip=ip)) + player.ip = ip + player.protocol = protocol + else: + logger.info("Adding new player with name: %s" % name) + player = Player(uuid=uuid, name=name, + last_seen=datetime.datetime.now(), + access_level=int(UserLevels.GUEST), + logged_in=False, + protocol=protocol, + client_id=-1, + ip=ip, + planet="", + on_ship=True) + player.ips = [IPAddress(ip=ip)] + session.add(player) + if uuid == self.config.owner_uuid: + player.access_level = int(UserLevels.OWNER) + + session.commit() + + return self._cache_and_return_from_session(session, player) + + def delete(self, player_cache): + with _autoclosing_session(self.sessionmaker) as session: + session.delete(player_cache.record) + session.commit() def who(self): - return self.session.query(Player).filter_by(logged_in=True).all() + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter_by(logged_in=True).all(), + collection=True, + ) + + def all(self): + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).all(), + collection=True, + ) + + def all_like(self, regex): + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter(Player.name.like(regex)).all(), + collection=True, + ) def whois(self, name): - return self.session.query(Player).filter(Player.logged_in == True, - func.lower(Player.name) == func.lower(name)).first() + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter( + Player.logged_in is True, + func.lower(Player.name) == func.lower(name), + ).first(), + ) def check_bans(self, ip): - return self.session.query(Ban).filter_by(ip=ip).first() is not None + with _autoclosing_session(self.sessionmaker) as session: + return session.query(Ban).filter_by(ip=ip).first() is not None def ban(self, ip): - self.session.add(Ban(ip=ip)) - try: - self.session.commit() - except: - self.session.rollback() - raise + with _autoclosing_session(self.sessionmaker) as session: + session.add(Ban(ip=ip)) + session.commit() + + @property + def bans(self): + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Ban).all(), + ) + + def delete_ban(self, ban_cache): + with _autoclosing_session(self.sessionmaker) as session: + session.delete(ban_cache.record) + session.commit() def get_by_name(self, name): - return self.session.query(Player).filter(func.lower(Player.name) == func.lower(name)).first() + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter(func.lower(Player.name) == func.lower(name)).first(), + ) def get_logged_in_by_name(self, name): - return self.session.query(Player).filter(Player.logged_in == True, - func.lower(Player.name) == func.lower(name)).first() + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter( + Player.logged_in, + func.lower(Player.name) == func.lower(name), + ).first(), + ) def permissions(level=UserLevels.OWNER): diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 41d3e51..a2b248b 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -26,7 +26,7 @@ def deactivate(self): del self.player_manager def check_logged_in(self): - for player in self.player_manager.session.query(Player).filter_by(logged_in=True).all(): + for player in self.player_manager.who(): if player.protocol not in self.factory.protocols.keys(): player.logged_in = False @@ -45,8 +45,11 @@ def on_client_connect(self, data): name=client_data.name, uuid=str(client_data.uuid), ip=self.protocol.transport.getPeer().host, - protocol=self.protocol.id) + protocol=self.protocol.id, + ) + return True + except AlreadyLoggedIn: self.reject_with_reason( "You're already logged in! If this is not the case, please wait 10 seconds and try again.") @@ -123,17 +126,16 @@ def delete_player(self, data): self.protocol.send_chat_message( "Couldn't find a player named %s. Please check the spelling and try again." % name) return False - self.player_manager.session.delete(player) + self.player_manager.delete(player) self.protocol.send_chat_message("Deleted player with name %s." % name) @permissions(UserLevels.ADMIN) def list_players(self, data): if len(data) == 0: - self.format_player_response(self.player_manager.session.query(Player).all()) + self.format_player_response(self.player_manager.all()) else: rx = re.sub(r"[\*]", "%", " ".join(data)) - self.format_player_response( - self.player_manager.session.query(Player).filter(Player.name.like(rx)).all()) + self.format_player_response(self.player_manager.all_like(rx)) def format_player_response(self, players): if len(players) <= 25: diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 7981779..394c3eb 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -76,4 +76,4 @@ def on_entity_create(self, data): self.logger.trace( "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", self.protocol.player.name, p_type) - return False \ No newline at end of file + return False diff --git a/server.py b/server.py index 3a09ea3..dddc8aa 100644 --- a/server.py +++ b/server.py @@ -27,6 +27,21 @@ logging.Logger.trace = lambda s, m, *a, **k: s._log(TRACE_LVL, m, a, **k) +def port_check(upstream_hostname, upstream_port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(1) + result = sock.connect_ex((upstream_hostname, upstream_port)) + + if result != 0: + sock.close() + return False + else: + sock.shutdown(SHUT_RDWR) + sock.close() + + return True + + class StarryPyServerProtocol(Protocol): """ The main protocol class for handling connections from Starbound clients. @@ -115,7 +130,7 @@ def connectionMade(self): def string_received(self, packet): """ - This method is called whenever a completed packet is received from the + This method is called whenever a completed packet is received from the client going to the Starbound server. This is the first and only time where these packets can be modified, stopped, or allowed. @@ -415,6 +430,7 @@ def send_chat_message(self, text, channel=0, world='', name=''): logger.trace("Built chat packet. Data: %s", chat_packet.encode("hex")) self.transport.write(chat_packet) logger.debug("Sent chat message with text: %s", text) + def write(self, data): """ Convenience method to send data to the client. @@ -440,6 +456,7 @@ def connectionLost(self, reason=connectionDone): except: self.logger.trace("Protocol was not in factory list. This should not happen.") + class ClientProtocol(Protocol): """ The protocol class which handles the connection to the Starbound server. @@ -460,7 +477,6 @@ def connectionMade(self): """ self.server_protocol.client_protocol = self - def string_received(self, packet): """ This method is called whenever a completed packet is received from the @@ -482,7 +498,6 @@ def string_received(self, packet): self.server_protocol.write( packet.original_data) - def dataReceived(self, data): """ Called whenever a packet is received. Generally this should not be @@ -504,6 +519,7 @@ def disconnect(self): self.transport.write(x) self.transport.abortConnection() + class StarryPyServerFactory(ServerFactory): """ Factory which creates `StarryPyServerProtocol` instances. @@ -569,7 +585,6 @@ def broadcast_planet(self, text, planet, name=''): except: logger.exception("Exception in broadcast.") - def buildProtocol(self, address): """ Builds the protocol to a given address. @@ -623,12 +638,14 @@ def buildProtocol(self, address): if __name__ == '__main__': logger = logging.getLogger('starrypy') logger.setLevel(9) + if TRACE: trace_logger = logging.FileHandler("trace.log") trace_logger.setLevel("TRACE") trace_logger.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")) logger.addHandler(trace_logger) logger.trace("Initialized trace logger.") + fh_d = logging.FileHandler("debug.log") fh_d.setLevel(logging.DEBUG) fh_w = logging.FileHandler("server.log") @@ -647,28 +664,29 @@ def buildProtocol(self, address): fh_d.setFormatter(debugfile_formatter) fh_w.setFormatter(logfile_formatter) sh.setFormatter(console_formatter) + if config.port_check: logger.debug("Port check enabled. Performing port check to %s:%d", config.upstream_hostname, config.upstream_port) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(1) - result = sock.connect_ex((config.upstream_hostname, config.upstream_port)) - if result != 0: + + if port_check(config.upstream_hostname, config.upstream_port): logger.critical("The starbound server is not connectable at the address %s:%d." % ( config.upstream_hostname, config.upstream_port)) logger.critical( "Please ensure that you are running starbound_server on the correct port and that is reflected in the StarryPy configuration.") sys.exit() - sock.shutdown(SHUT_RDWR) - sock.close() + logger.debug("Port check succeeded. Continuing.") + logger.info("Started StarryPy server version %s" % VERSION) factory = StarryPyServerFactory() logger.debug("Attempting to listen on TCP port %d", factory.config.bind_port) + try: reactor.listenTCP(factory.config.bind_port, factory, interface=factory.config.bind_address) except CannotListenError: logger.critical("Cannot listen on TCP port %d. Exiting.", factory.config.bind_port) sys.exit() + logger.info("Listening on port %s" % factory.config.bind_port) reactor.run() From 3e559cbb7e57817640d36718a50f9343babf35f1 Mon Sep 17 00:00:00 2001 From: slitherrr Date: Mon, 10 Feb 2014 17:33:40 -0800 Subject: [PATCH 19/95] Fix for plugin_storage --- plugins/core/player_manager/manager.py | 4 ++-- .../new_player_greeter_plugin/new_player_greeter_plugin.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index a86c680..235f031 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -164,7 +164,7 @@ def colored_name(self, colors): @property def storage(self): - caller = inspect.stack()[1][0].f_locals["self"].__class__.name + caller = inspect.stack()[2][0].f_locals["self"].__class__.name if self.plugin_storage is None: self.plugin_storage = {} try: @@ -175,7 +175,7 @@ def storage(self): @storage.setter def storage(self, store): - caller = inspect.stack()[1][0].f_locals["self"].__class__.name + caller = inspect.stack()[2][0].f_locals["self"].__class__.name self.plugin_storage[caller] = store def as_dict(self): diff --git a/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py b/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py index 2c33183..a97e6e3 100644 --- a/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py +++ b/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py @@ -16,9 +16,10 @@ def after_connect_response(self, data): if self.protocol.player is not None and self.protocol.player.logged_in: my_storage = self.protocol.player.storage if not 'given_starter_items' in my_storage or my_storage['given_starter_items'] == "False": - my_storage['given_starter_items'] = "True" self.give_items() self.send_greetings() + my_storage['given_starter_items'] = "True" + self.protocol.player.storage = my_storage self.logger.info("Gave starter items to %s.", self.protocol.player.name) def give_items(self): From 7485437b509f910fdd08336d770c8096e3d22c60 Mon Sep 17 00:00:00 2001 From: Marv Cool Date: Tue, 11 Feb 2014 11:21:12 +0100 Subject: [PATCH 20/95] adds "boneswoosh" to blocked projectiles this closes issue #95 --- config/config.json.default | 1 + 1 file changed, 1 insertion(+) diff --git a/config/config.json.default b/config/config.json.default index 0e4788b..2a7f3cd 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -70,6 +70,7 @@ "blacklist": [ "bomb", "bombblockexplosion", + "boneswoosh", "bouldersmashexplosion", "bouncycluster", "bouncyclustergrenade", From 7ca524ca54f51cac87e1dccc793ff74adb4e1aec Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Tue, 18 Feb 2014 18:25:59 -0600 Subject: [PATCH 21/95] Update for Enraged Koala. --- packets/packet_types.py | 84 ++++++++++--------- plugins/core/player_manager/plugin.py | 16 ++-- .../planet_protect/planet_protect_plugin.py | 4 +- plugins/warpy_plugin/warpy_plugin.py | 4 +- server.py | 2 + 5 files changed, 58 insertions(+), 52 deletions(-) diff --git a/packets/packet_types.py b/packets/packet_types.py index e574d74..6723602 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -15,47 +15,49 @@ class Packets(IntEnum): HANDSHAKE_CHALLENGE = 3 CHAT_RECEIVED = 4 UNIVERSE_TIME_UPDATE = 5 - CLIENT_CONNECT = 6 - CLIENT_DISCONNECT = 7 - HANDSHAKE_RESPONSE = 8 - WARP_COMMAND = 9 - CHAT_SENT = 10 - CLIENT_CONTEXT_UPDATE = 11 - WORLD_START = 12 - WORLD_STOP = 13 - TILE_ARRAY_UPDATE = 14 - TILE_UPDATE = 15 - TILE_LIQUID_UPDATE = 16 - TILE_DAMAGE_UPDATE = 17 - TILE_MODIFICATION_FAILURE = 18 - GIVE_ITEM = 19 - SWAP_IN_CONTAINER_RESULT = 20 - ENVIRONMENT_UPDATE = 21 - ENTITY_INTERACT_RESULT = 22 - MODIFY_TILE_LIST = 23 - DAMAGE_TILE = 24 - DAMAGE_TILE_GROUP = 25 - REQUEST_DROP = 26 - SPAWN_ENTITY = 27 - ENTITY_INTERACT = 28 - CONNECT_WIRE = 29 - DISCONNECT_ALL_WIRES = 30 - OPEN_CONTAINER = 31 - CLOSE_CONTAINER = 32 - SWAP_IN_CONTAINER = 33 - ITEM_APPLY_IN_CONTAINER = 34 - START_CRAFTING_IN_CONTAINER = 35 - STOP_CRAFTING_IN_CONTAINER = 36 - BURN_CONTAINER = 37 - CLEAR_CONTAINER = 38 - WORLD_UPDATE = 39 - ENTITY_CREATE = 40 - ENTITY_UPDATE = 41 - ENTITY_DESTROY = 42 - DAMAGE_NOTIFICATION = 43 - STATUS_EFFECT_REQUEST = 44 - UPDATE_WORLD_PROPERTIES = 45 - HEARTBEAT = 46 + CELESTIALRESPONSE = 6 + CLIENT_CONNECT = 7 + CLIENT_DISCONNECT = 8 + HANDSHAKE_RESPONSE = 9 + WARP_COMMAND = 10 + CHAT_SENT = 11 + CELESTIALREQUEST = 12 + CLIENT_CONTEXT_UPDATE = 13 + WORLD_START = 14 + WORLD_STOP = 15 + TILE_ARRAY_UPDATE = 16 + TILE_UPDATE = 17 + TILE_LIQUID_UPDATE = 18 + TILE_DAMAGE_UPDATE = 19 + TILE_MODIFICATION_FAILURE = 20 + GIVE_ITEM = 21 + SWAP_IN_CONTAINER_RESULT = 22 + ENVIRONMENT_UPDATE = 23 + ENTITY_INTERACT_RESULT = 24 + MODIFY_TILE_LIST = 25 + DAMAGE_TILE = 26 + DAMAGE_TILE_GROUP = 27 + REQUEST_DROP = 28 + SPAWN_ENTITY = 29 + ENTITY_INTERACT = 30 + CONNECT_WIRE = 31 + DISCONNECT_ALL_WIRES = 32 + OPEN_CONTAINER = 33 + CLOSE_CONTAINER = 34 + SWAP_IN_CONTAINER = 35 + ITEM_APPLY_IN_CONTAINER = 36 + START_CRAFTING_IN_CONTAINER = 37 + STOP_CRAFTING_IN_CONTAINER = 38 + BURN_CONTAINER = 39 + CLEAR_CONTAINER = 40 + WORLD_UPDATE = 41 + ENTITY_CREATE = 42 + ENTITY_UPDATE = 43 + ENTITY_DESTROY = 44 + DAMAGE_NOTIFICATION = 45 + STATUS_EFFECT_REQUEST = 46 + UPDATE_WORLD_PROPERTIES = 47 + HEARTBEAT = 48 class EntityType(IntEnum): diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index a2b248b..be39ca8 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -49,7 +49,6 @@ def on_client_connect(self, data): ) return True - except AlreadyLoggedIn: self.reject_with_reason( "You're already logged in! If this is not the case, please wait 10 seconds and try again.") @@ -93,19 +92,20 @@ def on_connect_response(self, data): def after_world_start(self, data): world_start = packets.world_start().parse(data.data) - coords = world_start.planet['config']['coordinate'] - if coords is not None: - parent_system = coords['parentSystem'] + if 'fuel.max' in world_start['world_properties']: + self.logger.info("Player %s is now on a ship.", self.protocol.player.name) + self.protocol.player.on_ship = True + else: + coords = world_start.planet['celestialParameters']['coordinate'] + parent_system = coords location = parent_system['location'] l = location self.protocol.player.on_ship = False planet = Planet(parent_system['sector'], l[0], l[1], l[2], - coords['planetaryOrbitNumber'], coords['satelliteOrbitNumber']) + coords['planet'], coords['satellite']) self.protocol.player.planet = str(planet) self.logger.debug("Player %s is now at planet: %s", self.protocol.player.name, str(planet)) - else: - self.logger.info("Player %s is now on a ship.", self.protocol.player.name) - self.protocol.player.on_ship = True + def on_client_disconnect(self, player): if self.protocol.player is not None and self.protocol.player.logged_in: diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 394c3eb..5c17ac5 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -69,11 +69,13 @@ def save(self): def on_entity_create(self, data): if self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level <= UserLevels.MODERATOR: entities = entity_create.parse(data.data) + print entities for entity in entities.entity: if entity.entity_type == EntityType.PROJECTILE: p_type = star_string("").parse(entity.entity) + print p_type if p_type in self.blacklist: - self.logger.trace( + self.logger.debug( "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", self.protocol.player.name, p_type) return False diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 1149d1f..3441974 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -1,6 +1,6 @@ from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels -from packets import warp_command_write, Packets +from packets import warp_command_write, Packets, warp_command from utility_functions import build_packet, move_ship_to_coords, extract_name @@ -73,7 +73,7 @@ def warp_player_to_player(self, from_string, to_string): else: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t='WARP_UP')) - from_protocol.client_protocol.transport.write(warp_packet) + print warp_packet.encode("hex") else: self.protocol.send_chat_message("No player by the name %s found." % to_string) self.protocol.send_chat_message(self.warp.__doc__) diff --git a/server.py b/server.py index dddc8aa..f3182e4 100644 --- a/server.py +++ b/server.py @@ -78,6 +78,8 @@ def __init__(self): packets.Packets.WORLD_STOP: self.world_stop, packets.Packets.TILE_ARRAY_UPDATE: self.tile_array_update, packets.Packets.TILE_UPDATE: self.tile_update, + packets.Packets.CELESTIALRESPONSE: lambda x: True, + packets.Packets.CELESTIALREQUEST: lambda x: True, packets.Packets.TILE_LIQUID_UPDATE: self.tile_liquid_update, packets.Packets.TILE_DAMAGE_UPDATE: self.tile_damage_update, packets.Packets.TILE_MODIFICATION_FAILURE: self.tile_modification_failure, From 1437fcf79ff4802160a859c1e34e3c0c7d4db3c7 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Tue, 18 Feb 2014 18:38:17 -0600 Subject: [PATCH 22/95] Fixes for bizarre enum34 behavior when used in pypy. --- .../admin_command_plugin.py | 2 +- plugins/core/player_manager/manager.py | 30 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index a8dfe03..02a83aa 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -86,7 +86,7 @@ def promote(self, data): self.logger.trace("Sending promotion message to promoter.") self.protocol.send_chat_message("%s: %s -> %s" % ( - player.colored_name(self.config.colors), str(UserLevels(old_rank)).split(".")[1], + player.colored_name(self.config.colors), UserLevels(old_rank), rank.upper())) self.logger.trace("Sending promotion message to promoted player.") try: diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 235f031..697b888 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -73,17 +73,25 @@ def as_dict(self): class Banned(Exception): pass +class _UserLevels(object): + ranks = dict( + GUEST = 0, + REGISTERED = 1, + MODERATOR = 10, + ADMIN = 100, + OWNER = 1000) + ranks_reverse = dict(zip(ranks.values(), ranks.keys())) + + def __call__(self, lvl, *args, **kwargs): + return self.ranks_reverse[lvl] + + def __getattr__(self, item): + if item in ['GUEST', 'REGISTERED', 'MODERATOR', 'ADMIN', 'OWNER']: + return super(_UserLevels, self).__getattribute__('ranks')[item] + else: + return super(_UserLevels, self).__getattribute__(item) -class IntEnum(int, Enum): - pass - - -class UserLevels(IntEnum): - GUEST = 0 - REGISTERED = 1 - MODERATOR = 10 - ADMIN = 100 - OWNER = 1000 +UserLevels = _UserLevels() class MutableDict(Mutable, dict): @@ -154,7 +162,7 @@ class Player(Base): def colored_name(self, colors): logger.trace("Building colored name.") - color = colors[str(UserLevels(self.access_level)).split(".")[1].lower()] + color = colors[UserLevels(self.access_level).lower()] logger.trace("Color is %s", color) name = self.name logger.trace("Name is %s", name) From 75f117f08077e8aef4d04f061a103d3010039f87 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Tue, 18 Feb 2014 21:25:12 -0600 Subject: [PATCH 23/95] Removed some debug code I stupidly left in that would spam the logs on a protected planet. --- plugins/planet_protect/planet_protect_plugin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 5c17ac5..0de7ef7 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -69,11 +69,9 @@ def save(self): def on_entity_create(self, data): if self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level <= UserLevels.MODERATOR: entities = entity_create.parse(data.data) - print entities for entity in entities.entity: if entity.entity_type == EntityType.PROJECTILE: p_type = star_string("").parse(entity.entity) - print p_type if p_type in self.blacklist: self.logger.debug( "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", From 44af4b7beba19ecaecf0782e4f2119a182a83c10 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Tue, 18 Feb 2014 23:30:57 -0600 Subject: [PATCH 24/95] Made all chat messaged strings translatable. --- plugins/admin_messenger/admin_messenger.py | 4 +- .../admin_command_plugin.py | 84 ++-- plugins/core/player_manager/manager.py | 2 +- plugins/core/player_manager/plugin.py | 13 +- .../starbound_config_manager.py | 4 +- plugins/motd_plugin/motd_plugin.py | 6 +- .../planet_protect/planet_protect_plugin.py | 16 +- .../plugin_manager_plugin.py | 34 +- plugins/warpy_plugin/warpy_plugin.py | 18 +- res/messages.po | 417 ++++++++++++++++++ server.py | 15 +- 11 files changed, 522 insertions(+), 91 deletions(-) create mode 100644 res/messages.po diff --git a/plugins/admin_messenger/admin_messenger.py b/plugins/admin_messenger/admin_messenger.py index 7444666..189263e 100644 --- a/plugins/admin_messenger/admin_messenger.py +++ b/plugins/admin_messenger/admin_messenger.py @@ -27,7 +27,7 @@ def message_admins(self, message): for protocol in self.factory.protocols.itervalues(): if protocol.player.access_level >= UserLevels.MODERATOR: protocol.send_chat_message( - "Received an admin message from %s: %s." % (self.protocol.player.name, + _("Received an admin message from %s: %s.") % (self.protocol.player.name, message.message[2:])) self.logger.info("Received an admin message from %s. Message: %s", self.protocol.player.name, message.message[2:]) @@ -35,7 +35,7 @@ def message_admins(self, message): @permissions(UserLevels.ADMIN) def broadcast_message(self, message): for protocol in self.factory.protocols.itervalues(): - protocol.send_chat_message("%sSERVER BROADCAST: %s%s" % ( + protocol.send_chat_message(_("%sSERVER BROADCAST: %s%s") % ( self.config.colors["admin"], message.message[3:], self.config.colors["default"])) self.logger.info("Broadcast from %s. Message: %s", self.protocol.player.name, message.message[3:]) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 02a83aa..bb47302 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -23,35 +23,35 @@ def activate(self): @permissions(UserLevels.GUEST) def who(self, data): - """Returns all current users on the server. Syntax: /who""" + __doc__ = _("""Returns all current users on the server. Syntax: /who""") who = [w.colored_name(self.config.colors) for w in self.player_manager.who()] - self.protocol.send_chat_message("%d players online: %s" % (len(who), ", ".join(who))) + self.protocol.send_chat_message("_(%d players online: %s)" % (len(who), ", ".join(who))) return False @permissions(UserLevels.GUEST) def planet(self, data): - """Displays who is on your current planet.""" + __doc__ = _("""Displays who is on your current planet.""") who = [w.colored_name(self.config.colors) for w in self.player_manager.who() if w.planet == self.protocol.player.planet and not w.on_ship] - self.protocol.send_chat_message("%d players on your current planet: %s" % (len(who), ", ".join(who))) + self.protocol.send_chat_message(_("%d players on your current planet: %s") % (len(who), ", ".join(who))) @permissions(UserLevels.ADMIN) def whois(self, data): - """Returns client data about the specified user. Syntax: /whois [user name]""" + __doc__ = _("""Returns client data about the specified user. Syntax: /whois [user name]""") name = " ".join(data) info = self.player_manager.whois(name) if info: self.protocol.send_chat_message( - "Name: %s\nUserlevel: %s\nUUID: %s\nIP address: %s\nCurrent planet: %s""" % ( + _("Name: %s\nUserlevel: %s\nUUID: %s\nIP address: %s\nCurrent planet: %s""") % ( info.colored_name(self.config.colors), UserLevels(info.access_level), info.uuid, info.ip, info.planet)) else: - self.protocol.send_chat_message("Player not found!") + self.protocol.send_chat_message(_("Player not found!")) return False @permissions(UserLevels.MODERATOR) def promote(self, data): - """Promotes/demoates a user to a specific rank. Syntax: /promote [username] [rank] (where rank is either: registered, moderator, admin, or guest))""" + __doc__ = _("""Promotes/demotes a user to a specific rank. Syntax: /promote [username] [rank] (where rank is either: registered, moderator, admin, or guest))""") self.logger.trace("Promote command received with the following data: %s" % ":".join(data)) if len(data) > 0: name = " ".join(data[:-1]) @@ -69,7 +69,7 @@ def promote(self, data): self.logger.trace( "The old rank was greater or equal to the current rank. Sending a message and returning.") self.protocol.send_chat_message( - "You cannot change that user's access level as they are at least at an equal level as you.") + _("You cannot change that user's access level as they are at least at an equal level as you.")) return if rank == "admin": self.make_admin(player) @@ -81,23 +81,23 @@ def promote(self, data): self.make_guest(player) else: self.logger.trace("Non-existent rank. Returning with a help message.") - self.protocol.send_chat_message("No such rank!\n" + self.promote.__doc__) + self.protocol.send_chat_message(_("No such rank!\n") + self.promote.__doc__) return self.logger.trace("Sending promotion message to promoter.") - self.protocol.send_chat_message("%s: %s -> %s" % ( + self.protocol.send_chat_message(_("%s: %s -> %s") % ( player.colored_name(self.config.colors), UserLevels(old_rank), rank.upper())) self.logger.trace("Sending promotion message to promoted player.") try: self.factory.protocols[player.protocol].send_chat_message( - "%s has promoted you to %s" % ( + _("%s has promoted you to %s") % ( self.protocol.player.colored_name(self.config.colors), rank.upper())) except KeyError: self.logger.trace("Promoted player is not logged in.") else: self.logger.trace("Player wasn't found. Sending chat message to player.") - self.protocol.send_chat_message("Player not found!\n" + self.promote.__doc__) + self.protocol.send_chat_message(_("Player not found!\n") + self.promote.__doc__) return else: self.logger.trace("Received blank promotion command. Sending help message.") @@ -125,7 +125,7 @@ def make_admin(self, player): @permissions(UserLevels.MODERATOR) def kick(self, data): - """Kicks a user from the server. Usage: /kick [username] [reason]""" + __doc__ = _("""Kicks a user from the server. Usage: /kick [username] [reason]""") name, reason = extract_name(data) if reason is None: reason = "no reason given" @@ -142,20 +142,20 @@ def kick(self, data): self.logger.info("%s kicked %s (reason: %s)", self.protocol.player.name, info.name, reason) else: - self.protocol.send_chat_message("Couldn't find a user by the name %s." % name) + self.protocol.send_chat_message(_("Couldn't find a user by the name %s.") % name) return False @permissions(UserLevels.ADMIN) def ban(self, data): - """Bans an IP (retrieved by /whois). Syntax: /ban [ip address]""" + __doc__ = _("""Bans an IP (retrieved by /whois). Syntax: /ban [ip address]""") try: ip = data[0] print socket.inet_aton(ip) self.logger.debug("Banning IP address %s" % ip) self.player_manager.ban(ip) - self.protocol.send_chat_message("Banned IP: %s" % ip) + self.protocol.send_chat_message(_("Banned IP: %s") % ip) self.logger.warning("%s banned IP: %s", self.protocol.player.name, ip) return False except socket.error: @@ -168,38 +168,38 @@ def ban_by_name(self, data): @permissions(UserLevels.ADMIN) def bans(self, data): - """Lists the currently banned IPs. Syntax: /bans""" + __doc__ = _("""Lists the currently banned IPs. Syntax: /bans""") self.protocol.send_chat_message("\n".join( - "IP: %s " % self.player_manager.bans)) + _("IP: %s ") % self.player_manager.bans)) @permissions(UserLevels.ADMIN) def unban(self, data): - """Unbans an IP. Syntax: /unban [ip address]""" + __doc__ = _("""Unbans an IP. Syntax: /unban [ip address]""") ip = data[0] for ban in self.player_manager.bans: if ban.ip == ip: self.player_manager.remove_ban(ban) - self.protocol.send_chat_message("Unbanned IP: %s" % ip) + self.protocol.send_chat_message(_("Unbanned IP: %s") % ip) break else: - self.protocol.send_chat_message("Couldn't find IP: %s" % ip) + self.protocol.send_chat_message(_("Couldn't find IP: %s") % ip) return False @permissions(UserLevels.ADMIN) def give_item(self, data): - """Gives an item to a player. Syntax: /give [target player] [item name] [optional: item count]""" + __doc__ = _("""Gives an item to a player. Syntax: /give [target player] [item name] [optional: item count]""") if len(data) >= 2: try: name, item = extract_name(data) except ValueError as e: - self.protocol.send_chat_message("Please check your syntax. %s" % str(e)) + self.protocol.send_chat_message(_("Please check your syntax. %s") % str(e)) return except AttributeError: self.protocol.send_chat_message( - "Please check that the username you are referencing exists. If it has spaces, please surround it by quotes.") + _("Please check that the username you are referencing exists. If it has spaces, please surround it by quotes.")) return except: - self.protocol.send_chat_message("An unknown error occured. %s" % str(e)) + self.protocol.send_chat_message(_("An unknown error occured. %s") % str(e)) target_player = self.player_manager.get_logged_in_by_name(name) target_protocol = self.factory.protocols[target_player.protocol] if target_player is not None: @@ -211,22 +211,22 @@ def give_item(self, data): item_count = 1 give_item_to_player(target_protocol, item_name, item_count) target_protocol.send_chat_message( - "%s has given you: %s (count: %s)" % ( + _("%s has given you: %s (count: %s)") % ( self.protocol.player.name, item_name, item_count)) - self.protocol.send_chat_message("Sent the item(s).") + self.protocol.send_chat_message(_("Sent the item(s).")) self.logger.info("%s gave %s %s (count: %s)", self.protocol.player.name, name, item_name, item_count) else: - self.protocol.send_chat_message("You have to give an item name.") + self.protocol.send_chat_message(_("You have to give an item name.")) else: - self.protocol.send_chat_message("Couldn't find name: %s" % name) + self.protocol.send_chat_message(_("Couldn't find name: %s" % name)) return False else: self.protocol.send_chat_message(self.give_item.__doc__) @permissions(UserLevels.MODERATOR) def mute(self, data): - """Mute a player. Syntax: /mute [player name]""" + __doc__ = _("""Mute a player. Syntax: /mute [player name]""") name = " ".join(data) player = self.player_manager.get_logged_in_by_name(name) if player is None: @@ -234,36 +234,36 @@ def mute(self, data): return target_protocol = self.factory.protocols[player.protocol] player.muted = True - target_protocol.send_chat_message("You have been muted.") - self.protocol.send_chat_message("%s has been muted." % name) + target_protocol.send_chat_message(_("You have been muted.")) + self.protocol.send_chat_message(_("%s has been muted.") % name) @permissions(UserLevels.MODERATOR) def unmute(self, data): - """Unmute a currently muted player. Syntax: /unmute [player name]""" + __doc__ = _("""Unmute a currently muted player. Syntax: /unmute [player name]""") name = " ".join(data) player = self.player_manager.get_logged_in_by_name(name) if player is None: - self.protocol.send_chat_message("Couldn't find a user by the name %s" % name) + self.protocol.send_chat_message(_("Couldn't find a user by the name %s") % name) return target_protocol = self.factory.protocols[player.protocol] player.muted = False - target_protocol.send_chat_message("You have been unmuted.") - self.protocol.send_chat_message("%s has been unmuted." % name) + target_protocol.send_chat_message(_("You have been unmuted.")) + self.protocol.send_chat_message(_("%s has been unmuted.") % name) @permissions(UserLevels.ADMIN) def passthrough(self, data): - """Sets the server to passthrough mode. *This is irreversible without restart.* Syntax: /passthrough""" + __doc__ = _("""Sets the server to passthrough mode. *This is irreversible without restart.* Syntax: /passthrough""") self.config.passthrough = True @permissions(UserLevels.ADMIN) def shutdown(self, data): - """Shutdown the server in n seconds. Syntax: /shutdown [number of seconds] (>0)""" + __doc__ = _("""Shutdown the server in n seconds. Syntax: /shutdown [number of seconds] (>0)""") try: x = float(data[0]) except ValueError: - self.protocol.send_chat_message("%s is not a number. Please enter a value in seconds." % data[0]) + self.protocol.send_chat_message(_("%s is not a number. Please enter a value in seconds.") % data[0]) return - self.factory.broadcast("SERVER ANNOUNCEMENT: Server is shutting down in %s seconds!" % data[0]) + self.factory.broadcast(_("SERVER ANNOUNCEMENT: Server is shutting down in %s seconds!") % data[0]) reactor.callLater(x, reactor.stop) @@ -275,7 +275,7 @@ def on_chat_sent(self, data): if self.protocol.player.muted and data.message[0] != self.config.command_prefix and data.message[ :2] != self.config.chat_prefix*2: self.protocol.send_chat_message( - "You are currently muted and cannot speak. You are limited to commands and admin chat (prefix your lines with %s for admin chat." % (self.config.chat_prefix*2)) + _("You are currently muted and cannot speak. You are limited to commands and admin chat (prefix your lines with %s for admin chat.") % (self.config.chat_prefix*2)) return False return True diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 697b888..762964c 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -362,7 +362,7 @@ def wrapped_function(self, *args, **kwargs): if self.protocol.player.access_level >= level: return f(self, *args, **kwargs) else: - self.protocol.send_chat_message("You are not an admin.") + self.protocol.send_chat_message(_("You are not an admin.")) return False return wrapped_function diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index be39ca8..6b02d1a 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -92,6 +92,7 @@ def on_connect_response(self, data): def after_world_start(self, data): world_start = packets.world_start().parse(data.data) + print world_start if 'fuel.max' in world_start['world_properties']: self.logger.info("Player %s is now on a ship.", self.protocol.player.name) self.protocol.player.on_ship = True @@ -118,16 +119,16 @@ def delete_player(self, data): name = " ".join(data) if self.player_manager.get_logged_in_by_name(name) is not None: self.protocol.send_chat_message( - "That player is currently logged in. Refusing to delete logged in character.") + _("That player is currently logged in. Refusing to delete logged in character.")) return False else: player = self.player_manager.get_by_name(name) if player is None: self.protocol.send_chat_message( - "Couldn't find a player named %s. Please check the spelling and try again." % name) + _("Couldn't find a player named %s. Please check the spelling and try again.") % name) return False self.player_manager.delete(player) - self.protocol.send_chat_message("Deleted player with name %s." % name) + self.protocol.send_chat_message(_("Deleted player with name %s.") % name) @permissions(UserLevels.ADMIN) def list_players(self, data): @@ -140,10 +141,10 @@ def list_players(self, data): def format_player_response(self, players): if len(players) <= 25: self.protocol.send_chat_message( - "Results: %s" % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players])) + _("Results: %s") % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players])) else: self.protocol.send_chat_message( - "Results: %s" % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players[:25]])) + _("Results: %s)" % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players[:25]]))) self.protocol.send_chat_message( - "And %d more. Narrow it down with SQL like syntax. Feel free to use a *, it will be replaced appropriately." % ( + _("And %d more. Narrow it down with SQL like syntax. Feel free to use a *, it will be replaced appropriately.") % ( len(players) - 25)) diff --git a/plugins/core/starbound_config_manager/starbound_config_manager.py b/plugins/core/starbound_config_manager/starbound_config_manager.py index b1e7066..bfb9027 100644 --- a/plugins/core/starbound_config_manager/starbound_config_manager.py +++ b/plugins/core/starbound_config_manager/starbound_config_manager.py @@ -34,6 +34,6 @@ def activate(self): @permissions(UserLevels.GUEST) def spawn(self, data): - """Moves your ship to spawn. Syntax: /move_ship_to_spawn""" + __doc__ = _("""Moves your ship to spawn. Syntax: /spawn""") self.plugins['warpy_plugin'].move_player_ship(self.protocol, [x for x in self._spawn]) - self.protocol.send_chat_message("Moving your ship to spawn.") \ No newline at end of file + self.protocol.send_chat_message(_("Moving your ship to spawn.")) \ No newline at end of file diff --git a/plugins/motd_plugin/motd_plugin.py b/plugins/motd_plugin/motd_plugin.py index 172b1b9..aa7c372 100644 --- a/plugins/motd_plugin/motd_plugin.py +++ b/plugins/motd_plugin/motd_plugin.py @@ -25,11 +25,11 @@ def after_connect_response(self, data): self.send_motd() def send_motd(self): - self.protocol.send_chat_message("Message of the Day:\n%s" % self._motd) + self.protocol.send_chat_message(_("Message of the Day:\n%s") % self._motd) @permissions(UserLevels.GUEST) def motd(self, data): - """Displays the message of the day. Usage: /motd""" + __doc__ = _("""Displays the message of the day. Usage: /motd""") if len(data) == 0: self.send_motd() else: @@ -37,7 +37,7 @@ def motd(self, data): @permissions(UserLevels.MODERATOR) def set_motd(self, motd): - """Sets the message of the day to a new value. Usage: /set_motd [New message of the day]""" + __doc__ = _("""Sets the message of the day to a new value. Usage: /set_motd [New message of the day]""") try: self._motd = " ".join(motd).encode("utf-8") self.config.plugin_config['motd'] = self._motd diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 0de7ef7..583bce4 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -32,34 +32,34 @@ def planet_check(self): @permissions(UserLevels.ADMIN) def protect(self, data): - """Protects the current planet. Only registered users can build on protected planets. Syntax: /protect""" + __doc__ = _("""Protects the current planet. Only registered users can build on protected planets. Syntax: /protect""") planet = self.protocol.player.planet on_ship = self.protocol.player.on_ship if on_ship: - self.protocol.send_chat_message("Can't protect ships (at the moment)") + self.protocol.send_chat_message(_("Can't protect ships (at the moment)")) return if planet not in self.protected_planets: self.protected_planets.append(planet) - self.protocol.send_chat_message("Planet successfully protected.") + self.protocol.send_chat_message(_("Planet successfully protected.")) self.logger.info("Protected planet %s", planet) else: - self.protocol.send_chat_message("Planet is already protected!") + self.protocol.send_chat_message(_("Planet is already protected!")) self.save() @permissions(UserLevels.ADMIN) def unprotect(self, data): - """Removes the protection from the current planet. Syntax: /unprotect""" + __doc__ = _("""Removes the protection from the current planet. Syntax: /unprotect""") planet = self.protocol.player.planet on_ship = self.protocol.player.on_ship if on_ship: - self.protocol.send_chat_message("Can't protect ships (at the moment)") + self.protocol.send_chat_message(_("Can't protect ships (at the moment)")) return if planet in self.protected_planets: self.protected_planets.remove(planet) - self.protocol.send_chat_message("Planet successfully unprotected.") + self.protocol.send_chat_message(_("Planet successfully unprotected.")) self.logger.info("Unprotected planet %s", planet) else: - self.protocol.send_chat_message("Planet is not protected!") + self.protocol.send_chat_message(_("Planet is not protected!")) self.save() def save(self): diff --git a/plugins/plugin_manager_plugin/plugin_manager_plugin.py b/plugins/plugin_manager_plugin/plugin_manager_plugin.py index 6a8a26a..8d2ce1e 100644 --- a/plugins/plugin_manager_plugin/plugin_manager_plugin.py +++ b/plugins/plugin_manager_plugin/plugin_manager_plugin.py @@ -15,62 +15,62 @@ def plugin_manager(self): @permissions(UserLevels.ADMIN) def list_plugins(self, data): - """Lists all currently loaded plugins. Syntax: /list_plugins""" - self.protocol.send_chat_message("Currently loaded plugins: %s" % " ".join( + __doc__ = """Lists all currently loaded plugins. Syntax: /list_plugins""" + self.protocol.send_chat_message(_("Currently loaded plugins: %s") % " ".join( [plugin.name for plugin in self.plugin_manager.plugins.itervalues() if plugin.active])) inactive = [plugin.name for plugin in self.plugin_manager.plugins.itervalues() if not plugin.active] if len(inactive) > 0: - self.protocol.send_chat_message("Inactive plugins: %s" % " ".join( + self.protocol.send_chat_message(_("Inactive plugins: %s") % " ".join( [plugin.name for plugin in self.plugin_manager.plugins.itervalues() if not plugin.active])) @permissions(UserLevels.ADMIN) def disable_plugin(self, data): - """Disables a currently activated plugin. Syntax: /disable_plugin [plugin name]""" + __doc__ = """Disables a currently activated plugin. Syntax: /disable_plugin [plugin name]""" self.logger.debug("disable_plugin called: %s" " ".join(data)) if len(data) == 0: - self.protocol.send_chat_message("You have to specify a plugin.") + self.protocol.send_chat_message(_("You have to specify a plugin.")) return try: plugin = self.plugin_manager.get_by_name(data[0]) except PluginNotFound: - self.protocol.send_chat_message("Couldn't find a plugin with the name %s" % data[0]) + self.protocol.send_chat_message(_("Couldn't find a plugin with the name %s") % data[0]) return if plugin is self: - self.protocol.send_chat_message("Sorry, this plugin can't be deactivated.") + self.protocol.send_chat_message(_("Sorry, this plugin can't be deactivated.")) return if not plugin.active: - self.protocol.send_chat_message("That plugin is already deactivated.") + self.protocol.send_chat_message(_("That plugin is already deactivated.")) return plugin.deactivate() - self.protocol.send_chat_message("Successfully deactivated plugin.") + self.protocol.send_chat_message(_("Successfully deactivated plugin.")) @permissions(UserLevels.ADMIN) def enable_plugin(self, data): - """Enables a currently deactivated plugin. Syntax: /enable_plugin [plugin name]""" + __doc__ = """Enables a currently deactivated plugin. Syntax: /enable_plugin [plugin name]""" self.logger.debug("enable_plugin called: %s", " ".join(data)) if len(data) == 0: - self.protocol.send_chat_message("You have to specify a plugin.") + self.protocol.send_chat_message(_("You have to specify a plugin.")) return try: plugin = self.plugin_manager.get_by_name(data[0]) except PluginNotFound: - self.protocol.send_chat_message("Couldn't find a plugin with the name %s" % data[0]) + self.protocol.send_chat_message(_("Couldn't find a plugin with the name %s") % data[0]) return if plugin.active: - self.protocol.send_chat_message("That plugin is already active.") + self.protocol.send_chat_message(_("That plugin is already active.")) return plugin.activate() - self.protocol.send_chat_message("Successfully activated plugin.") + self.protocol.send_chat_message(_("Successfully activated plugin.")) @permissions(UserLevels.GUEST) def help(self, data): - """Prints help messages for plugin commands. Syntax: /help [command]""" + __doc__ = """Prints help messages for plugin commands. Syntax: /help [command]""" if len(data) > 0: command = data[0].lower() func = self.plugins['command_dispatcher'].commands.get(command, None) if func is None: - self.protocol.send_chat_message("Couldn't find a command with the name %s" % command) + self.protocol.send_chat_message(_("Couldn't find a command with the name %s") % command) self.protocol.send_chat_message("%s%s: %s" % (self.config.command_prefix, command, func.__doc__)) else: available = [] @@ -79,5 +79,5 @@ def help(self, data): available.append(name) available.sort(key=str.lower) self.protocol.send_chat_message( - "Available commands: %s\nAlso try /help command" % ", ".join(available)) + _("Available commands: %s\nAlso try /help command") % ", ".join(available)) return True \ No newline at end of file diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 3441974..272800b 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -19,7 +19,7 @@ def activate(self): @permissions(UserLevels.ADMIN) def warp(self, name): - """Warps you to a player's ship, or a player to another player's ship. Syntax: /warp [player name] OR /warp [player 1] [player 2]""" + __doc__ = _("""Warps you to a player's ship, or a player to another player's ship. Syntax: /warp [player name] OR /warp [player 1] [player 2]""") if len(name) == 0: self.protocol.send_chat_message(self.warp.__doc__) return @@ -40,7 +40,7 @@ def warp(self, name): @permissions(UserLevels.ADMIN) def move_ship(self, location): - """Move your ship to another player or specific coordinates. Syntax: /move_ship [player_name] OR /move_ship [from player] [to player]""" + __doc__ = _("""Move your ship to another player or specific coordinates. Syntax: /move_ship [player_name] OR /move_ship [from player] [to player]""") try: first_name, rest = extract_name(location) if not rest: @@ -51,7 +51,7 @@ def move_ship(self, location): self.protocol.send_chat_message(str(e)) self.protocol.send_chat_message(self.move_ship.__doc__) except AttributeError: - self.protocol.send_chat_message("Couldn't find one or both of the users you specified.") + self.protocol.send_chat_message(_("Couldn't find one or both of the users you specified.")) def warp_self_to_player(self, name): self.logger.debug("Warp command called by %s to %s", self.protocol.player.name, name) @@ -75,18 +75,18 @@ def warp_player_to_player(self, from_string, to_string): warp_command_write(t='WARP_UP')) print warp_packet.encode("hex") else: - self.protocol.send_chat_message("No player by the name %s found." % to_string) + self.protocol.send_chat_message(_("No player by the name %s found.") % to_string) self.protocol.send_chat_message(self.warp.__doc__) return else: - self.protocol.send_chat_message("No player by the name %s found." % from_string) + self.protocol.send_chat_message(_("No player by the name %s found.") % from_string) self.protocol.send_chat_message(self.warp.__doc__) def move_player_ship(self, protocol, location): if len(location) < 5: - self.logger.warning("Couldn't derive a warp location in move_player_ship. Coordinates given: %s", + self.logger.warning(_("Couldn't derive a warp location in move_player_ship. Coordinates given: %s"), ":".join(location)) - self.protocol.send_chat_message("Sorry, an error occurred.") + self.protocol.send_chat_message(_("Sorry, an error occurred.")) return if len(location) == 5: satellite = 0 @@ -105,7 +105,7 @@ def move_own_ship_to_player(self, player_name): raise ValueError if t.planet == u"": self.protocol.send_chat_message( - "Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped down to a planet since logging in?" % t.name) + _("Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped down to a planet since logging in?") % t.name) return self.move_player_ship(self.protocol, t.planet.split(":")) @@ -117,7 +117,7 @@ def move_player_ship_to_other(self, from_player, to_player): raise ValueError if t.planet == u"": self.protocol.send_chat_message( - "Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped to a planet since logging in?" % to_player) + _("Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped to a planet since logging in?") % to_player) return self.move_player_ship(self.factory.protocols[f.protocol], t.planet.split(":")) diff --git a/res/messages.po b/res/messages.po new file mode 100644 index 0000000..4a9792f --- /dev/null +++ b/res/messages.po @@ -0,0 +1,417 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-18 23:27-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: plugins/planet_protect/planet_protect_plugin.py:35 +msgid "" +"Protects the current planet. Only registered users can build on protected " +"planets. Syntax: /protect" +msgstr "" + +#: plugins/planet_protect/planet_protect_plugin.py:39 +#: plugins/planet_protect/planet_protect_plugin.py:55 +msgid "Can't protect ships (at the moment)" +msgstr "" + +#: plugins/planet_protect/planet_protect_plugin.py:43 +msgid "Planet successfully protected." +msgstr "" + +#: plugins/planet_protect/planet_protect_plugin.py:46 +msgid "Planet is already protected!" +msgstr "" + +#: plugins/planet_protect/planet_protect_plugin.py:51 +msgid "Removes the protection from the current planet. Syntax: /unprotect" +msgstr "" + +#: plugins/planet_protect/planet_protect_plugin.py:59 +msgid "Planet successfully unprotected." +msgstr "" + +#: plugins/planet_protect/planet_protect_plugin.py:62 +msgid "Planet is not protected!" +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:22 +msgid "" +"Warps you to a player's ship, or a player to another player's ship. Syntax: /" +"warp [player name] OR /warp [player 1] [player 2]" +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:43 +msgid "" +"Move your ship to another player or specific coordinates. Syntax: /move_ship " +"[player_name] OR /move_ship [from player] [to player]" +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:54 +msgid "Couldn't find one or both of the users you specified." +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:78 +#: plugins/warpy_plugin/warpy_plugin.py:82 +#, python-format +msgid "No player by the name %s found." +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:87 +#, python-format +msgid "" +"Couldn't derive a warp location in move_player_ship. Coordinates given: %s" +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:89 +msgid "Sorry, an error occurred." +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:108 +#, python-format +msgid "" +"Sorry, we don't have a tracked planet location for %s. Perhaps they haven't " +"warped down to a planet since logging in?" +msgstr "" + +#: plugins/warpy_plugin/warpy_plugin.py:120 +#, python-format +msgid "" +"Sorry, we don't have a tracked planet location for %s. Perhaps they haven't " +"warped to a planet since logging in?" +msgstr "" + +#: plugins/admin_messenger/admin_messenger.py:30 +#, python-format +msgid "Received an admin message from %s: %s." +msgstr "" + +#: plugins/admin_messenger/admin_messenger.py:38 +#, python-format +msgid "%sSERVER BROADCAST: %s%s" +msgstr "" + +#: plugins/motd_plugin/motd_plugin.py:28 +#, python-format +msgid "" +"Message of the Day:\n" +"%s" +msgstr "" + +#: plugins/motd_plugin/motd_plugin.py:32 +msgid "Displays the message of the day. Usage: /motd" +msgstr "" + +#: plugins/motd_plugin/motd_plugin.py:40 +msgid "" +"Sets the message of the day to a new value. Usage: /set_motd [New message of " +"the day]" +msgstr "" + +#: plugins/core/starbound_config_manager/starbound_config_manager.py:37 +msgid "Moves your ship to spawn. Syntax: /spawn" +msgstr "" + +#: plugins/core/starbound_config_manager/starbound_config_manager.py:39 +msgid "Moving your ship to spawn." +msgstr "" + +#: plugins/core/player_manager/plugin.py:122 +msgid "" +"That player is currently logged in. Refusing to delete logged in character." +msgstr "" + +#: plugins/core/player_manager/plugin.py:128 +#, python-format +msgid "" +"Couldn't find a player named %s. Please check the spelling and try again." +msgstr "" + +#: plugins/core/player_manager/plugin.py:131 +#, python-format +msgid "Deleted player with name %s." +msgstr "" + +#: plugins/core/player_manager/plugin.py:144 +#, python-format +msgid "Results: %s" +msgstr "" + +#: plugins/core/player_manager/plugin.py:147 +#, python-format +msgid "Results: %s)" +msgstr "" + +#: plugins/core/player_manager/plugin.py:149 +#, python-format +msgid "" +"And %d more. Narrow it down with SQL like syntax. Feel free to use a *, it " +"will be replaced appropriately." +msgstr "" + +#: plugins/core/player_manager/manager.py:365 +msgid "You are not an admin." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:26 +msgid "Returns all current users on the server. Syntax: /who" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:33 +msgid "Displays who is on your current planet." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:36 +#, python-format +msgid "%d players on your current planet: %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:40 +msgid "" +"Returns client data about the specified user. Syntax: /whois [user name]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:45 +#, python-format +msgid "" +"Name: %s\n" +"Userlevel: %s\n" +"UUID: %s\n" +"IP address: %s\n" +"Current planet: %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:49 +msgid "Player not found!" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:54 +msgid "" +"Promotes/demotes a user to a specific rank. Syntax: /promote [username] " +"[rank] (where rank is either: registered, moderator, admin, or guest))" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:72 +msgid "" +"You cannot change that user's access level as they are at least at an equal " +"level as you." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:84 +msgid "No such rank!\n" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:88 +#, python-format +msgid "%s: %s -> %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:94 +#, python-format +msgid "%s has promoted you to %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:100 +msgid "Player not found!\n" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:128 +msgid "Kicks a user from the server. Usage: /kick [username] [reason]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:145 +#, python-format +msgid "Couldn't find a user by the name %s." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:152 +msgid "Bans an IP (retrieved by /whois). Syntax: /ban [ip address]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:158 +#, python-format +msgid "Banned IP: %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:171 +msgid "Lists the currently banned IPs. Syntax: /bans" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:173 +#, python-format +msgid "IP: %s " +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:177 +msgid "Unbans an IP. Syntax: /unban [ip address]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:182 +#, python-format +msgid "Unbanned IP: %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:185 +#, python-format +msgid "Couldn't find IP: %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:190 +msgid "" +"Gives an item to a player. Syntax: /give [target player] [item name] " +"[optional: item count]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:195 +#, python-format +msgid "Please check your syntax. %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:199 +msgid "" +"Please check that the username you are referencing exists. If it has spaces, " +"please surround it by quotes." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:202 +#, python-format +msgid "An unknown error occured. %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:214 +#, python-format +msgid "%s has given you: %s (count: %s)" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:216 +msgid "Sent the item(s)." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:220 +msgid "You have to give an item name." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:222 +#, python-format +msgid "Couldn't find name: %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:229 +msgid "Mute a player. Syntax: /mute [player name]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:237 +msgid "You have been muted." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:238 +#, python-format +msgid "%s has been muted." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:242 +msgid "Unmute a currently muted player. Syntax: /unmute [player name]" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:246 +#, python-format +msgid "Couldn't find a user by the name %s" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:250 +msgid "You have been unmuted." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:251 +#, python-format +msgid "%s has been unmuted." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:255 +msgid "" +"Sets the server to passthrough mode. *This is irreversible without restart.* " +"Syntax: /passthrough" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:260 +msgid "" +"Shutdown the server in n seconds. Syntax: /shutdown [number of seconds] (>0)" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:264 +#, python-format +msgid "%s is not a number. Please enter a value in seconds." +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:266 +#, python-format +msgid "SERVER ANNOUNCEMENT: Server is shutting down in %s seconds!" +msgstr "" + +#: plugins/core/admin_commands_plugin/admin_command_plugin.py:278 +#, python-format +msgid "" +"You are currently muted and cannot speak. You are limited to commands and " +"admin chat (prefix your lines with %s for admin chat." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:19 +#, python-format +msgid "Currently loaded plugins: %s" +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:23 +#, python-format +msgid "Inactive plugins: %s" +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:31 +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:53 +msgid "You have to specify a plugin." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:36 +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:58 +#, python-format +msgid "Couldn't find a plugin with the name %s" +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:39 +msgid "Sorry, this plugin can't be deactivated." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:42 +msgid "That plugin is already deactivated." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:46 +msgid "Successfully deactivated plugin." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:61 +msgid "That plugin is already active." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:64 +msgid "Successfully activated plugin." +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:73 +#, python-format +msgid "Couldn't find a command with the name %s" +msgstr "" + +#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:82 +#, python-format +msgid "" +"Available commands: %s\n" +"Also try /help command" +msgstr "" diff --git a/server.py b/server.py index f3182e4..fcdc04b 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,7 @@ # -*- coding: UTF-8 -*- from _socket import SHUT_RDWR +import gettext +import locale import logging from uuid import uuid4 import sys @@ -636,11 +638,22 @@ def buildProtocol(self, address): protocol = ClientFactory.buildProtocol(self, address) protocol.server_protocol = self.server_protocol return protocol +def init_localization(): + locale.setlocale(locale.LC_ALL, '') + loc = locale.getlocale() + filename = "res/messages_%s.mo" % locale.getlocale()[0][0:2] + try: + print "Opening message file %s for locale %s." % (filename, loc[0]) + trans = gettext.GNUTranslations(open(filename, "rb" )) + except IOError: + print "Locale not found. Using default messages." + trans = gettext.NullTranslations() + trans.install() if __name__ == '__main__': + init_localization() logger = logging.getLogger('starrypy') logger.setLevel(9) - if TRACE: trace_logger = logging.FileHandler("trace.log") trace_logger.setLevel("TRACE") From dc1cba746e4f78d782391ca1701a90993bc3a081 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Tue, 18 Feb 2014 23:39:32 -0600 Subject: [PATCH 25/95] Fixed logging level of planet warp. --- config/config.json.default | 2 +- plugins/core/player_manager/plugin.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 2a7f3cd..f6f0406 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -148,7 +148,7 @@ "auto_activate": true, "name_removal_regexes": [ "\\^#[\\w]+;", - "[^ \\w]+" + "[\\w]+" ] }, "plugin_manager": { diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 6b02d1a..07b632f 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -105,7 +105,7 @@ def after_world_start(self, data): planet = Planet(parent_system['sector'], l[0], l[1], l[2], coords['planet'], coords['satellite']) self.protocol.player.planet = str(planet) - self.logger.debug("Player %s is now at planet: %s", self.protocol.player.name, str(planet)) + self.logger.info("Player %s is now at planet: %s", self.protocol.player.name, str(planet)) def on_client_disconnect(self, player): From f3b9e3686858c7c13d4d2c2dbd5fcb1369bfbcb2 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 00:02:49 -0600 Subject: [PATCH 26/95] Added force command to /protect. --- plugins/planet_protect/planet_protect_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 583bce4..a5939f5 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -35,7 +35,7 @@ def protect(self, data): __doc__ = _("""Protects the current planet. Only registered users can build on protected planets. Syntax: /protect""") planet = self.protocol.player.planet on_ship = self.protocol.player.on_ship - if on_ship: + if on_ship and not ("force" in " ".join(data).lower()): self.protocol.send_chat_message(_("Can't protect ships (at the moment)")) return if planet not in self.protected_planets: @@ -51,7 +51,7 @@ def unprotect(self, data): __doc__ = _("""Removes the protection from the current planet. Syntax: /unprotect""") planet = self.protocol.player.planet on_ship = self.protocol.player.on_ship - if on_ship: + if on_ship and not ("force" in " ".join(data).lower()): self.protocol.send_chat_message(_("Can't protect ships (at the moment)")) return if planet in self.protected_planets: From 4ad1bfaa45315a14b73b6a6c823a48ce468c2c81 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 15:00:31 -0600 Subject: [PATCH 27/95] Fixed issue with names not returning any results. --- plugins/core/player_manager/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 762964c..bfa0bda 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -306,7 +306,7 @@ def whois(self, name): return self._cache_and_return_from_session( session, session.query(Player).filter( - Player.logged_in is True, + Player.logged_in, func.lower(Player.name) == func.lower(name), ).first(), ) From 351c82ed1a944f068a9d1a9432aa239b545925b5 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 15:30:26 -0600 Subject: [PATCH 28/95] Removed extraneous debug prints. --- plugins/core/player_manager/plugin.py | 1 - plugins/planet_protect/planet_protect_plugin.py | 2 ++ plugins/warpy_plugin/warpy_plugin.py | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 07b632f..cab6804 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -92,7 +92,6 @@ def on_connect_response(self, data): def after_world_start(self, data): world_start = packets.world_start().parse(data.data) - print world_start if 'fuel.max' in world_start['world_properties']: self.logger.info("Player %s is now on a ship.", self.protocol.player.name) self.protocol.player.on_ship = True diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index a5939f5..e057ef1 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -22,6 +22,7 @@ def activate(self): self.blacklist = self.config.plugin_config.get("blacklist", []) self.player_manager = self.plugins.get("player_manager", []) self.protect_everything = self.config.plugin_config.get("protect_everything", []) + self.block_all = False def planet_check(self): if self.protect_everything or ( @@ -71,6 +72,7 @@ def on_entity_create(self, data): entities = entity_create.parse(data.data) for entity in entities.entity: if entity.entity_type == EntityType.PROJECTILE: + if self.block_all: return False p_type = star_string("").parse(entity.entity) if p_type in self.blacklist: self.logger.debug( diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 272800b..af7524f 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -70,10 +70,11 @@ def warp_player_to_player(self, from_string, to_string): warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t="WARP_OTHER_SHIP", player=to_player.name.encode('utf-8'))) + else: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t='WARP_UP')) - print warp_packet.encode("hex") + else: self.protocol.send_chat_message(_("No player by the name %s found.") % to_string) self.protocol.send_chat_message(self.warp.__doc__) From a3aa937a1c0527b732c81d9860695e46661c271b Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 16:02:07 -0600 Subject: [PATCH 29/95] Put bans command back in to list bans. --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index bb47302..c750791 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -14,7 +14,7 @@ class UserCommandPlugin(SimpleCommandPlugin): name = "user_management_commands" depends = ['command_dispatcher', 'player_manager'] commands = ["who", "whois", "promote", "kick", "ban", "give_item", "planet", "mute", "unmute", - "passthrough", "shutdown"] + "passthrough", "shutdown", "bans"] auto_activate = True def activate(self): From bd6d5b464f3fd1d50bb7ac637a0109d2ddb232b4 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 16:06:03 -0600 Subject: [PATCH 30/95] Fixed /warp command. --- plugins/warpy_plugin/warpy_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index af7524f..049ac04 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -74,7 +74,7 @@ def warp_player_to_player(self, from_string, to_string): else: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t='WARP_UP')) - + from_protocol.client_protocol.transport.write(warp_packet) else: self.protocol.send_chat_message(_("No player by the name %s found.") % to_string) self.protocol.send_chat_message(self.warp.__doc__) From 1e2470371c6b725f6eb4628ec0165abb1a4b8939 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 16:11:48 -0600 Subject: [PATCH 31/95] Fixed formatting of /bans. --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index c750791..8a8916c 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -170,7 +170,7 @@ def ban_by_name(self, data): def bans(self, data): __doc__ = _("""Lists the currently banned IPs. Syntax: /bans""") self.protocol.send_chat_message("\n".join( - _("IP: %s ") % self.player_manager.bans)) + [_("IP: %s ") % x.ip for x in self.player_manager.bans])) @permissions(UserLevels.ADMIN) def unban(self, data): From f13b1ae229b9ce6343662d2ebbf3bfaeed8c461d Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 20:05:53 -0600 Subject: [PATCH 32/95] Disabled default portcheck since it's broken. --- config/config.json.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json.default b/config/config.json.default index f6f0406..0f3042a 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -165,7 +165,7 @@ } }, "plugin_path": "plugins", - "port_check": true, + "port_check": false, "reap_time": 10, "server_connect_timeout": 5, "starbound_path": "/opt/starbound/", From 24e11f178f462c04c27829e18640574134309dca Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Thu, 20 Feb 2014 20:16:05 -0600 Subject: [PATCH 33/95] Fixed portcheck. --- config/config.json.default | 2 +- server.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 0f3042a..f6f0406 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -165,7 +165,7 @@ } }, "plugin_path": "plugins", - "port_check": false, + "port_check": true, "reap_time": 10, "server_connect_timeout": 5, "starbound_path": "/opt/starbound/", diff --git a/server.py b/server.py index fcdc04b..28292e9 100644 --- a/server.py +++ b/server.py @@ -684,7 +684,7 @@ def init_localization(): logger.debug("Port check enabled. Performing port check to %s:%d", config.upstream_hostname, config.upstream_port) - if port_check(config.upstream_hostname, config.upstream_port): + if not port_check(config.upstream_hostname, config.upstream_port): logger.critical("The starbound server is not connectable at the address %s:%d." % ( config.upstream_hostname, config.upstream_port)) logger.critical( From d75ac465a359251fe7b670cca503f6a7da0aac72 Mon Sep 17 00:00:00 2001 From: CarrotsAreMediocre Date: Fri, 21 Feb 2014 01:33:34 -0600 Subject: [PATCH 34/95] Fixed permissions on make_guest. --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 8a8916c..7171089 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -103,7 +103,7 @@ def promote(self, data): self.logger.trace("Received blank promotion command. Sending help message.") self.protocol.send_chat_message(self.promote.__doc__) - @permissions(UserLevels.OWNER) + @permissions(UserLevels.MODERATOR) def make_guest(self, player): self.logger.trace("Setting %s to GUEST", player.name) player.access_level = UserLevels.GUEST From 984ca9ae7d3ee2ee61df032acf3807c668dedeb4 Mon Sep 17 00:00:00 2001 From: pluto Date: Tue, 13 May 2014 00:45:58 -0700 Subject: [PATCH 35/95] Fixed up a bad query causing server to load slow. Also fixed some minor bugs. --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 2 +- plugins/core/player_manager/manager.py | 5 +++-- plugins/planet_protect/planet_protect_plugin.py | 2 ++ plugins/plugin_manager_plugin/plugin_manager_plugin.py | 4 +++- server.py | 2 ++ 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 423ddca..746e246 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -52,7 +52,7 @@ def whois(self, data): if len(data) == 0: self.protocol.send_chat_message(self.whois.__doc__) return - name = " ".join(data) + name, garbage = extract_name(data) info = self.player_manager.whois(name) if info and self.protocol.player.access_level >= UserLevels.ADMIN: self.protocol.send_chat_message( diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 4348164..3dda534 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -223,11 +223,12 @@ class PlayerManager(object): def __init__(self, config): self.config = config migrate_db(self.config) + logger.info("Loading player database.") self.engine = create_engine('sqlite:///%s' % path.preauthChild(self.config.player_db).path) Base.metadata.create_all(self.engine) self.sessionmaker = sessionmaker(bind=self.engine, autoflush=True) with _autoclosing_session(self.sessionmaker) as session: - for player in session.query(Player).all(): + for player in session.query(Player).filter_by(logged_in=True).all(): player.logged_in = False player.protocol = None session.commit() @@ -409,7 +410,7 @@ def wrapped_function(self, *args, **kwargs): if self.protocol.player.access_level >= level: return f(self, *args, **kwargs) else: - self.protocol.send_chat_message("You are not an admin.") + self.protocol.send_chat_message("You are not authorized to do this.") return False return wrapped_function diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 10407c6..d2ef278 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -51,9 +51,11 @@ def protect(self, data): addplayer = self.protocol.player.org_name first_name_color = self.protocol.player.colored_name(self.config.colors) else: + self.logger.info("stream: %s" % data) addplayer = data[0] try: addplayer, rest = extract_name(data) + self.logger.info("name: %s" % str(addplayer)) addplayer = self.player_manager.get_by_name(addplayer).org_name first_name_color = self.player_manager.get_by_org_name(addplayer).colored_name(self.config.colors) except: diff --git a/plugins/plugin_manager_plugin/plugin_manager_plugin.py b/plugins/plugin_manager_plugin/plugin_manager_plugin.py index 4eb2232..0687b38 100644 --- a/plugins/plugin_manager_plugin/plugin_manager_plugin.py +++ b/plugins/plugin_manager_plugin/plugin_manager_plugin.py @@ -69,6 +69,8 @@ def help(self, data): func = self.plugins['command_dispatcher'].commands.get(command, None) if func is None: self.protocol.send_chat_message("Couldn't find a command with the name ^yellow;%s" % command) + elif func.level > self.protocol.player.access_level: + self.protocol.send_chat_message("You do not have access to this command.") else: #self.protocol.send_chat_message("%s%s: %s" % (self.config.command_prefix, command, func.__doc__)) self.protocol.send_chat_message("%s" % func.__doc__) @@ -80,4 +82,4 @@ def help(self, data): available.sort(key=str.lower) self.protocol.send_chat_message( "Available commands: ^yellow;%s\n^green;Get more help on commands with ^yellow;/help [command]" % "^green;, ^yellow;".join(available)) - return True \ No newline at end of file + return True diff --git a/server.py b/server.py index 6070a4f..f3fefad 100644 --- a/server.py +++ b/server.py @@ -22,6 +22,8 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet +import timeit + VERSION = "1.4.3" From 996d9f261ad1c72ab08aed14c8aac45401bb160b Mon Sep 17 00:00:00 2001 From: kharidiron Date: Tue, 13 May 2014 01:08:43 -0700 Subject: [PATCH 36/95] remove an unneeded import, and add to the version number --- server.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server.py b/server.py index f3fefad..06c1ccf 100644 --- a/server.py +++ b/server.py @@ -22,9 +22,7 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet -import timeit - -VERSION = "1.4.3" +VERSION = "1.4.3_r2" def port_check(upstream_hostname, upstream_port): From a675e094e9af4d14366e23220cbfeee7e96faf3a Mon Sep 17 00:00:00 2001 From: kharidiron Date: Tue, 13 May 2014 20:56:38 -0700 Subject: [PATCH 37/95] fixed issues with player name extraction. Moved most commands over to the extract_name function. --- config/config.json.default | 9 +++++---- .../admin_commands_plugin/admin_command_plugin.py | 12 +++++------- plugins/warpy_plugin/warpy_plugin.py | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index bb747d8..7239a01 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -103,15 +103,16 @@ "bad_packets": [ "CONNECT_WIRE", "DISCONNECT_ALL_WIRES", - "ENTITY_INTERACT", - "OPEN_CONTAINER", - "CLOSE_CONTAINER", "SWAP_IN_CONTAINER", "DAMAGE_TILE", "DAMAGE_TILE_GROUP", - "REQUEST_DROP", "MODIFY_TILE_LIST" ], + "bad_packets_ship": [ + "ENTITY_INTERACT", + "OPEN_CONTAINER", + "CLOSE_CONTAINER" + ], "bad_packets_mild": [ "CONNECT_WIRE", "DISCONNECT_ALL_WIRES", diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 746e246..0bfd3ba 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -13,9 +13,8 @@ class UserCommandPlugin(SimpleCommandPlugin): """ name = "user_management_commands" depends = ['command_dispatcher', 'player_manager'] - commands = ["who", "whoami", "whois", "promote", "kick", "ban", "ban_list", "unban", "item", "planet", "mute", - "unmute", - "passthrough", "shutdown", "timestamps"] + commands = ["who", "whoami", "whois", "promote", "kick", "ban", "ban_list", "unban", "item", + "planet", "mute", "unmute", "passthrough", "shutdown", "timestamps"] auto_activate = True def activate(self): @@ -72,8 +71,7 @@ def whois(self, data): def promote(self, data): """Promotes/demotes a player to a specific rank.\nSyntax: /promote (player) (rank) (where rank is either: guest, registered, moderator, admin, or owner)""" if len(data) > 0: - name = " ".join(data[:-1]) - rank = data[-1].lower() + name, rank = extract_name(data) player = self.player_manager.get_by_name(name) if player is not None: old_rank = player.access_level @@ -279,7 +277,7 @@ def item(self, data): @permissions(UserLevels.MODERATOR) def mute(self, data): """Mute a player.\nSyntax: /mute (player)""" - name = " ".join(data) + name, garbage = extract_name(data) player = self.player_manager.get_logged_in_by_name(name) if player is None: self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;" % name) @@ -293,7 +291,7 @@ def mute(self, data): @permissions(UserLevels.MODERATOR) def unmute(self, data): """Unmute a currently muted player.\nSyntax: /unmute (player)""" - name = " ".join(data) + name, garbage = extract_name(data) player = self.player_manager.get_logged_in_by_name(name) if player is None: self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;" % name) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 0e836a1..215fe2b 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -60,7 +60,7 @@ def warp_ship(self, location): self.move_player_ship_to_other(first_name, second_name) def warp_self_to_player(self, name): - name = " ".join(name) + name, rest = extract_name(data) self.warp_player_to_player(self.protocol.player.name, name) def warp_player_to_player(self, from_string, to_string): From 830be324f44dc9c8d10a14534ee0220d24056185 Mon Sep 17 00:00:00 2001 From: kharidiron Date: Tue, 13 May 2014 20:58:52 -0700 Subject: [PATCH 38/95] forgot to increment version --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index 06c1ccf..2e27d00 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,7 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet -VERSION = "1.4.3_r2" +VERSION = "1.4.3_r3" def port_check(upstream_hostname, upstream_port): From 2c9c195bf1776ad11edb590290b3e4721efeb0d3 Mon Sep 17 00:00:00 2001 From: Tsunder Date: Thu, 22 May 2014 01:50:30 -0400 Subject: [PATCH 39/95] motd bloat message removal displays only the message from set_motd or whatever rather than the 5 or so line message --- plugins/motd_plugin/motd_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/motd_plugin/motd_plugin.py b/plugins/motd_plugin/motd_plugin.py index b45344b..fd33a3b 100644 --- a/plugins/motd_plugin/motd_plugin.py +++ b/plugins/motd_plugin/motd_plugin.py @@ -28,7 +28,7 @@ def send_motd(self): #self.protocol.send_chat_message("^yellow;%s" % self._motd) if not self.config.server_name: self.config.server_name = "MY" - self.protocol.send_chat_message("^#00FFFF;WELCOME TO ^#FF0000;%s^#00FFFF; STARBOUND SERVER\n^yellow;------------------------------------------------------------------\n^green;Type: ^yellow;/help ^green;for list of available commands\n^green;Type: ^yellow;/starteritems ^green;for some starter items ^cyan;(once)\n^green;Type: ^yellow;/fuel ^green;to get your daily fuel supply ^cyan;(once a day)\n^green;Legend: ^#F7434C;Owner^yellow;, ^#C443F7;Admin^yellow;, ^#4385F7;Moderator^yellow;, ^#A0F743;Registered user^yellow;, Guest\n^yellow;------------------------------------------------------------------\n^cyan;%s" % (self.config.server_name, self._motd)) + self.protocol.send_chat_message("%s" % (self.config.server_name, self._motd)) @permissions(UserLevels.GUEST) def motd(self, data): From 80c40da1228b462bc357127e011ca5ead45fbbec Mon Sep 17 00:00:00 2001 From: Tsunder Date: Thu, 22 May 2014 01:51:26 -0400 Subject: [PATCH 40/95] Update motd_plugin.py --- plugins/motd_plugin/motd_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/motd_plugin/motd_plugin.py b/plugins/motd_plugin/motd_plugin.py index fd33a3b..f4c154b 100644 --- a/plugins/motd_plugin/motd_plugin.py +++ b/plugins/motd_plugin/motd_plugin.py @@ -28,7 +28,7 @@ def send_motd(self): #self.protocol.send_chat_message("^yellow;%s" % self._motd) if not self.config.server_name: self.config.server_name = "MY" - self.protocol.send_chat_message("%s" % (self.config.server_name, self._motd)) + self.protocol.send_chat_message("%s" % (self._motd)) @permissions(UserLevels.GUEST) def motd(self, data): From c1f3b3b160422a389b8f93287603902f5e3253c1 Mon Sep 17 00:00:00 2001 From: kharidiron Date: Wed, 21 May 2014 23:46:37 -0700 Subject: [PATCH 41/95] Added new plugin, and interpreter for client_context packs. made a few other small fixes. --- config/.config.json.swp | Bin 0 -> 16384 bytes config/bookmarks/pois.json | 1 + loggy.txt | Bin 0 -> 1678601 bytes packet_stream.py | 3 +- packets/packet_types.py | 13 ++++-- plugins/admin_chatter/__init__.py | 1 + plugins/admin_chatter/admin_chatter.py | 47 +++++++++++++++++++++ plugins/admin_messenger/admin_messenger.py | 2 +- server.py | 2 +- 9 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 config/.config.json.swp create mode 100644 config/bookmarks/pois.json create mode 100644 loggy.txt create mode 100644 plugins/admin_chatter/__init__.py create mode 100644 plugins/admin_chatter/admin_chatter.py diff --git a/config/.config.json.swp b/config/.config.json.swp new file mode 100644 index 0000000000000000000000000000000000000000..eba874d52719c61da7033072529c342d168333bd GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/config/bookmarks/pois.json b/config/bookmarks/pois.json new file mode 100644 index 0000000..ffa2a82 --- /dev/null +++ b/config/bookmarks/pois.json @@ -0,0 +1 @@ +[["alpha:18199896:-7537982:-29875958:4:0", "spawn"], ["alpha:-46228686:-57338749:-26585271:8:0", "buildplanet"], ["sectorx:1999:1997:-14622445:3:6", "featheropolis"], ["sectorx:-1:-3:5876938:4:0", "pvparena"], ["sectorx:32704560:41511008:-3580117:7:1", "charon"]] diff --git a/loggy.txt b/loggy.txt new file mode 100644 index 0000000000000000000000000000000000000000..76dddbc07c2a2ac83153cd8835351d197f95c926 GIT binary patch literal 1678601 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
OP`k;32#Y{96v08a)us6Uhwz=36F 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�a9 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 ro0bbRKcXF}VbM{KHf%#O)aXM$f;n7g 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 i_jnZ=17n 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¥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 ^yellow;" + else: + timestamp = "" + if len(data) == 0: + self.protocol.send_chat_message(self.modchat.__doc__) + return + try: + message = " ".join(data) + for protocol in self.factory.protocols.itervalues(): + if protocol.player.access_level >= UserLevels.MODERATOR: + protocol.send_chat_message(timestamp + + "%sModChat: ^yellow;<%s^yellow;> %s%s" % (self.config.colors["admin"], self.protocol.player.colored_name(self.config.colors), + self.config.colors["admin"],message.decode("utf-8"))) + self.logger.info("Received an admin message from %s. Message: %s", self.protocol.player.name, + message.decode("utf-8")) + except ValueError as e: + self.protocol.send_chat_message(self.modchat.__doc__) + except TypeError as e: + self.protocol.send_chat_message(self.modchat.__doc__) + + @permissions(UserLevels.MODERATOR) + def mc(self, data): + """Allows mod-only chatting.\nSyntax: /modchat (msg)""" + self.modchat(data) diff --git a/plugins/admin_messenger/admin_messenger.py b/plugins/admin_messenger/admin_messenger.py index bf43d14..a21be7e 100644 --- a/plugins/admin_messenger/admin_messenger.py +++ b/plugins/admin_messenger/admin_messenger.py @@ -5,7 +5,7 @@ class AdminMessenger(BasePlugin): - """Adds support to message moderators/admins/owner with a ## prefixed message.""" + """Adds support to message moderators/admins/owner with a @@ prefixed message.""" name = "admin_messenger" depends = ['player_manager'] auto_activate = True diff --git a/server.py b/server.py index 2e27d00..45a6cbc 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,7 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet -VERSION = "1.4.3_r3" +VERSION = "1.4.3_r4" def port_check(upstream_hostname, upstream_port): From f7bbeb7eac24b429d70bf63d7e0bd97a0f26d085 Mon Sep 17 00:00:00 2001 From: kharidiron Date: Wed, 21 May 2014 23:49:23 -0700 Subject: [PATCH 42/95] remove some files from the git list that don't need to be there --- .gitignore | 6 +++++- config/.config.json.swp | Bin 16384 -> 0 bytes loggy.txt | Bin 1678601 -> 0 bytes 3 files changed, 5 insertions(+), 1 deletion(-) delete mode 100644 config/.config.json.swp delete mode 100644 loggy.txt diff --git a/.gitignore b/.gitignore index d4e4c2f..b7edc60 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,8 @@ nosetests.xml *.db *.db-journal *.log -.idea/ \ No newline at end of file +.idea/ +bookmarks/ + +# Vim mess cleanup +*.swp diff --git a/config/.config.json.swp b/config/.config.json.swp deleted file mode 100644 index eba874d52719c61da7033072529c342d168333bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 diff --git a/loggy.txt b/loggy.txt deleted file mode 100644 index 76dddbc07c2a2ac83153cd8835351d197f95c926..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1678601 zcmeFa2Ut}}5-5D{CFh(ZgNg*nQ9y};h~y-qcUvbNf}diZJiv3Xj1_*i?e0r0eU zbzu|Y7v&c*^$;Nx{-;bu`2O9gnEP3K{Gjp+H7L{XU!?A8Ze{Oc z%jV_;J;!Ec?qzOa?rF{c+j&b!!t?(B{DNH+K$U&}T+c&<<~EL|-xGXn@|IrqKGuiW zj+#4pS`&JM+We)Y&ekqork1YGpuAR|KcCa{@CJ{$dD%N#|5F}2_pF^=y{tWd`<{iX ztE02IhvV0S*1t6Le<=5N=KM~SOO| z@8#-Y`hQ{cFHgI9fM#gv^$*m|t(+l&xAye3cKPR4_M2UXq{uFT+aHaM-rckO z)5}o*XARnqg_FIf9mvVX!_}GXnARaSVNuX43JXi|i%I=PzLI>BQoqqJ{zCze+nIaV zTiJWKx)9o19b%IpggUB2Y;3%1r5X z9DpPMDFBB6NCS`oAPe9K0672(0F(eI15g2=4nPZlHUJ#}x&ZV67y>v6z!-oDfHMHh z09XL91YiZg27oO9I{@|o8~`{2a0TE70BXw~0K5SB0PqEH7JwfBe*gghE&#X)APB%^ z09OE91rQ1#9KbaI5dfk9L<5Kc5C`BEfCK=y0VDxP0dNPvT>z;7?g2;x@BlzMfD8bc z0I~o)1dt6N2S6@>JOBj%3IP-YCz-!&|tjJ)7{-dO0; z^ZmWLe3AzT2rN>oTvO)!E~L7j%ZS6R6qgnfIreOe>S{_f)$+lX_l-6Ulo8d>2hY}$ z1^bm#34beZeV^USD zQgm0r)>M+x=bJ6KDq9x|%c^;|?4!RuParWPn4)8RFxS19h}Dj(9?RlUSv0LX6mr*E zy03rb^2HkKT;{ql4To|cPOc`Se3#+wY4PIQ7r9iIoi(TAi{IYad#5@lucag^DaD;@ zpM*4>d&6Rg-Bfabd|f-2O|bU%$1`GeJ__$6$C>a_>T|Le=)}u6^y^&NR|f|k=^P$g zzn&yJkQ!lm#&NcHg@kqBU2ERhfX|L61-DP z;JD{?7hr!6e<$kgXE~qJmy{iAHU*KZFV7c*Q67^yOX)UqldmkkweN}vo|fpU78lL| zVI3>tQp&-`)1S2+2yYf8V;$INH+8OadH z-7KxpiBCH~Q)1B0LN3p(C#FzsGIB3(wrfObM2h!45q-W%Q@?RC;+YYzzBy6W7D@SJ zx{h|CK{z)-0J4C((G#b0Y`j$^uPu&?#fE|TwIuVMw>7Nx$l@i{+u_3cs;^fWgYF*r zdWJe~vQn6{$mw?VdPG`yCTf!Km9QUyGNbFoPd5+tKURsB&^ayfpdeA$uT=P;b*2)h zc)lN(w&mK9nhP&zJm1YpYVO(pRrT8TUM;gXM)a+d4_R+0PInQXpRY=2k2$n4-N{ck z_w`PgP>A_m$JQl^8H&0WBHA3G>lgMABDrkZ6;>YG$XqfIzyG0p(_J~-_x@$y_SX$} zHQUDEcFbWOb2KB9Wu`e zsPTQqy_s;<+#)QDZvRca2f`onwgyp+o@{iu$JM?FS%*dJ`^1-IeKumBjBY!P-;~@T ztRwtNxx!{FZ#iqn3N^*@#UC5eH1%0uuYE`Uoax?C(Bbp!$UipJ@l%)q@o#!gfM6rW zel9mzXiTITVRUIuN|JW}N_M#9#oL2s5kd|0mVe;ik;lkc%KjOM3MEFUP+^1$HQK3w z3Pa-`H1hw-e*y#n+P?;gAV3gegbEQxs1T!_3L2RYvi`w;F#b~_(El|M6%w@98AOHj z(m~Lf^&Te-WTVD;mFivEU(Vcnb&P`H^b9t8@};%+-9Zh0Jl6E(>rBg2^n$)PR{F?V8V-4HSAKlt-VUK=G_I&;Rj1nXcHISC_F|<>`3uHTQIGX|;w~)vwsU$uHa^7rp1u#7%l!xbe(;|F zl1v5+aE1V}2P0G%F+zn2BUG5tMg=svy*vFsB?`z41;N>5NI^m(kWi8mo}_{&so_Z) zc#;;Lq=P5v;YkK~at}PoxH}1SPIwXtPom&SEO-(dp2UGCaepTN1ETmJA^Ai8@sL1u zCq-L3i}*4BV@8l+gbF!Es9<8o%#6kvGmv#hb@iR0?H3OHN1EZ^ME^rI@Lm3gtTLkT z>?v8C-Z9~eK6`;PcFu(Km3*xnqU~IFO_zN54Xoq)iltE_foBVSnaqn)g%?Lfedfk0 zHX64#HxPzp^+s5W8aH{#I9+L;G^=h+u3xnaa9_rLb?tu8ql}wNi7F2T_7mvhURcvG zUp=gSAzdZYr{1sf>T%1Q!iy5&tG5pw9~jT;Id=N+f-0i_x$WHoebGaGuUQvAw2G>q z7<%jYdGmbL%GbM@EArpQo}Q*nF~g~=@8e>*QvPvum_%wTdN@F;lR1%J#5+q{@=e#p z#P=6tZ{dz*2p+h0r6+cu{cDNCS!3VcOo|xB`*#$Ua$ZVbIA8gNlqf3Aq+j5@O<_x= zTjitt{PIjfo~wAZe<)f1`}{X7;h=E#{@BDg>$G%~Y(uz*9lC zx)=FYdD`D^J|iz&?ruc1`4U08-%Ib8zheSIAZi@<%-bX<%bTLN-)dkcQ^LJOF^L7WEkX z4s5u{Sdg9tunzz>06Fj*u<@c?z!d=E4S@Xs2lt?*3ly+wA%X1^36&cvLq7m(fJ63G zP@Wwd^9J}0*m03103e$xcoqrSQkB3J*k6$Y;Q4uwb^zCd0LTFlgWsY23Bd2bUW
OP`k;32#Y{96v08a)us6Uhwz=36F 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�a9 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 ro0bbRKcXF}VbM{KHf%#O)aXM$f;n7g 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 i_jnZ=17n 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¥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 Date: Thu, 22 May 2014 07:24:02 -0700 Subject: [PATCH 43/95] Made SBReddit-specific changes. I'll branch later for proper upstream versioning --- plugins/admin_chatter/__init__.py | 1 - plugins/core/admin_commands_plugin/admin_command_plugin.py | 2 +- plugins/mod_chatter/__init__.py | 1 + .../admin_chatter.py => mod_chatter/mod_chatter.py} | 6 +++--- plugins/planet_protect/planet_protect_plugin.py | 6 +++--- plugins/warpy_plugin/warpy_plugin.py | 7 ++++--- 6 files changed, 12 insertions(+), 11 deletions(-) delete mode 100644 plugins/admin_chatter/__init__.py create mode 100644 plugins/mod_chatter/__init__.py rename plugins/{admin_chatter/admin_chatter.py => mod_chatter/mod_chatter.py} (94%) diff --git a/plugins/admin_chatter/__init__.py b/plugins/admin_chatter/__init__.py deleted file mode 100644 index 40ca90f..0000000 --- a/plugins/admin_chatter/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from admin_chatter import AdminChatter diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 0bfd3ba..eca6e09 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -234,7 +234,7 @@ def unban_by_name(self, data): self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;." % name) return False - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def item(self, data): """Gives an item to a player.\nSyntax: /item (player) (item) [count]""" if len(data) >= 2: diff --git a/plugins/mod_chatter/__init__.py b/plugins/mod_chatter/__init__.py new file mode 100644 index 0000000..4719056 --- /dev/null +++ b/plugins/mod_chatter/__init__.py @@ -0,0 +1 @@ +from mod_chatter import ModChatter diff --git a/plugins/admin_chatter/admin_chatter.py b/plugins/mod_chatter/mod_chatter.py similarity index 94% rename from plugins/admin_chatter/admin_chatter.py rename to plugins/mod_chatter/mod_chatter.py index 1a5c066..14ac6c4 100644 --- a/plugins/admin_chatter/admin_chatter.py +++ b/plugins/mod_chatter/mod_chatter.py @@ -4,15 +4,15 @@ from datetime import datetime -class AdminChatter(SimpleCommandPlugin): +class ModChatter(SimpleCommandPlugin): """Adds support for moderators/admins/owner group chatter.""" - name = "admin_chatter" + name = "mod_chatter" depends = ['command_dispatcher', 'player_manager'] commands = ["modchat", "mc"] auto_activate = True def activate(self): - super(AdminChatter, self).activate() + super(ModChatter, self).activate() self.prefix = self.config.chat_prefix self.player_manager = self.plugins['player_manager'].player_manager diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index d2ef278..171d395 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -43,7 +43,7 @@ def planet_check(self): else: return True - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def protect(self, data): """Protects the current planet. Only administrators and allowed players can build on protected planets.\nSyntax: /protect [player]""" on_ship = self.protocol.player.on_ship @@ -109,7 +109,7 @@ def protect_all(self, data): self.save() - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def protect_list(self, data): """Displays players registered to the protected planet.\nSyntax: /protect_list""" planet = self.protocol.player.planet @@ -123,7 +123,7 @@ def protect_list(self, data): else: self.protocol.send_chat_message("Planet is not protected!") - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def unprotect(self, data): """Removes the protection from the current planet, or removes a registered player.\nSyntax: /unprotect [player]""" planet = self.protocol.player.planet diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 215fe2b..75e5a1c 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -17,7 +17,7 @@ def activate(self): super(Warpy, self).activate() self.player_manager = self.plugins['player_manager'].player_manager - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def warp(self, name): """Warps you to a player's ship (or player to player).\nSyntax: /warp [player] (to player)""" if len(name) == 0: @@ -38,7 +38,7 @@ def warp(self, name): return self.warp_player_to_player(first_name, second_name) - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def warp_ship(self, location): """Warps a player ship to another players ship.\nSyntax: /warp_ship [player] (to player)""" if len(location) == 0: @@ -60,7 +60,8 @@ def warp_ship(self, location): self.move_player_ship_to_other(first_name, second_name) def warp_self_to_player(self, name): - name, rest = extract_name(data) + name = " ".join(name) + #name, rest = extract_name(data) self.warp_player_to_player(self.protocol.player.name, name) def warp_player_to_player(self, from_string, to_string): From 8fdd9cd0dc6fb93e5f401433248ed6756c54873b Mon Sep 17 00:00:00 2001 From: kharidiron Date: Thu, 22 May 2014 07:24:32 -0700 Subject: [PATCH 44/95] Increment version number --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index 45a6cbc..e96c9df 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,7 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet -VERSION = "1.4.3_r4" +VERSION = "1.4.3_r5" def port_check(upstream_hostname, upstream_port): From 68bd0e97bb8906e20a5d9e17cabc9300d1413501 Mon Sep 17 00:00:00 2001 From: kharidiron Date: Thu, 22 May 2014 12:30:17 -0700 Subject: [PATCH 45/95] added the ability to filter planet-side chat from IRC channel (increase privacy). Changed chat colors around a bit at Astraltor's suggestion . --- packets/packet_types.py | 2 +- plugins/admin_messenger/admin_messenger.py | 4 ++-- plugins/irc_plugin/irc_plugin.py | 5 +++-- plugins/mod_chatter/mod_chatter.py | 2 +- server.py | 1 + 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packets/packet_types.py b/packets/packet_types.py index 6270e01..92cb7f6 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -127,7 +127,7 @@ def _decode(self, obj, context): chat_sent = lambda name="chat_sent": Struct(name, star_string("message"), - Padding(1)) + Byte("chat_channel")) client_connect = lambda name="client_connect": Struct(name, VLQ("asset_digest_length"), diff --git a/plugins/admin_messenger/admin_messenger.py b/plugins/admin_messenger/admin_messenger.py index a21be7e..42b7339 100644 --- a/plugins/admin_messenger/admin_messenger.py +++ b/plugins/admin_messenger/admin_messenger.py @@ -33,8 +33,8 @@ def message_admins(self, message): for protocol in self.factory.protocols.itervalues(): if protocol.player.access_level >= UserLevels.MODERATOR: protocol.send_chat_message(timestamp + - "%sADMIN: ^yellow;<%s^yellow;> %s%s" % (self.config.colors["admin"], self.protocol.player.colored_name(self.config.colors), - self.config.colors["admin"],message.message[2:].decode("utf-8"))) + "%sADMIN: ^yellow;<%s^yellow;> %s%s" % (self.config.colors["moderator"], self.protocol.player.colored_name(self.config.colors), + self.config.colors["moderator"],message.message[2:].decode("utf-8"))) self.logger.info("Received an admin message from %s. Message: %s", self.protocol.player.name, message.message[2:].decode("utf-8")) diff --git a/plugins/irc_plugin/irc_plugin.py b/plugins/irc_plugin/irc_plugin.py index bca877a..6f3bafa 100644 --- a/plugins/irc_plugin/irc_plugin.py +++ b/plugins/irc_plugin/irc_plugin.py @@ -48,8 +48,9 @@ def deactivate(self): def on_chat_sent(self, data): parsed = chat_sent().parse(data.data) if not parsed.message.startswith('/'): - for p in self.irc_factory.irc_clients.itervalues(): - p.msg(self.channel, "<%s> %s" % (self.protocol.player.name.encode("utf-8"), parsed.message.encode("utf-8"))) + if parsed.chat_channel == 0: + for p in self.irc_factory.irc_clients.itervalues(): + p.msg(self.channel, "<%s> %s" % (self.protocol.player.name.encode("utf-8"), parsed.message.encode("utf-8"))) return True def on_client_connect(self, data): diff --git a/plugins/mod_chatter/mod_chatter.py b/plugins/mod_chatter/mod_chatter.py index 14ac6c4..62f2111 100644 --- a/plugins/mod_chatter/mod_chatter.py +++ b/plugins/mod_chatter/mod_chatter.py @@ -21,7 +21,7 @@ def modchat(self, data): """Allows mod-only chatting.\nSyntax: /modchat (msg)""" now = datetime.now() if self.config.chattimestamps: - timestamp = "^cyan;<" + now.strftime("%H:%M") + "> ^yellow;" + timestamp = "^red;<" + now.strftime("%H:%M") + "> ^yellow;" else: timestamp = "" if len(data) == 0: diff --git a/server.py b/server.py index e96c9df..77d4e92 100644 --- a/server.py +++ b/server.py @@ -453,6 +453,7 @@ def connectionLost(self, reason=connectionDone): self.factory.protocols.pop(self.id) except: logger.info("Protocol was not in factory list. This should not happen.") + logger.info("protocol id: %s" % self.id) finally: logger.info("Lost connection from IP: %s", self.transport.getPeer().host) self.transport.abortConnection() From 4e57f600d17ce933a8e63a5886168c095f2a273d Mon Sep 17 00:00:00 2001 From: Tsunder Date: Sun, 8 Jun 2014 13:31:12 -0400 Subject: [PATCH 46/95] starter items nerf enough fuel for one intersystem trip. (200 fuel) no longer has enough food for a month or bandages to make a battle medic jealous also no free monies --- config/config.json.default | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 7239a01..e2b2743 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -87,13 +87,12 @@ "starteritems_plugin": { "auto_activate": true, "items": [ - [ "bandage", 20 ], - [ "burger", 20 ], + [ "bandage", 5 ], + [ "burger", 2 ], [ "stoneaxe", 1 ], [ "stonehoe", 1 ], [ "stonepickaxe", 1 ], - [ "solariumore", 30 ], - [ "money", 1000 ] + [ "solariumore", 20 ] ], "message": "You were given a set of starter items ;)" }, From ec18d04591a4d2f6579a50d425490367e3771707 Mon Sep 17 00:00:00 2001 From: kharidiron Date: Sun, 8 Jun 2014 15:07:27 -0700 Subject: [PATCH 47/95] some fixes --- .../admin_command_plugin.py | 3 ++- plugins/irc_plugin/irc_plugin.py | 5 ++-- plugins/motd_plugin/motd_plugin.py | 2 +- .../planet_protect/planet_protect_plugin.py | 27 +++++++++++-------- plugins/warpy_plugin/warpy_plugin.py | 3 +-- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index eca6e09..798328d 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -71,7 +71,8 @@ def whois(self, data): def promote(self, data): """Promotes/demotes a player to a specific rank.\nSyntax: /promote (player) (rank) (where rank is either: guest, registered, moderator, admin, or owner)""" if len(data) > 0: - name, rank = extract_name(data) + name = " ".join(data[:-1]) + rank = data[-1].lower() player = self.player_manager.get_by_name(name) if player is not None: old_rank = player.access_level diff --git a/plugins/irc_plugin/irc_plugin.py b/plugins/irc_plugin/irc_plugin.py index 6f3bafa..bca877a 100644 --- a/plugins/irc_plugin/irc_plugin.py +++ b/plugins/irc_plugin/irc_plugin.py @@ -48,9 +48,8 @@ def deactivate(self): def on_chat_sent(self, data): parsed = chat_sent().parse(data.data) if not parsed.message.startswith('/'): - if parsed.chat_channel == 0: - for p in self.irc_factory.irc_clients.itervalues(): - p.msg(self.channel, "<%s> %s" % (self.protocol.player.name.encode("utf-8"), parsed.message.encode("utf-8"))) + for p in self.irc_factory.irc_clients.itervalues(): + p.msg(self.channel, "<%s> %s" % (self.protocol.player.name.encode("utf-8"), parsed.message.encode("utf-8"))) return True def on_client_connect(self, data): diff --git a/plugins/motd_plugin/motd_plugin.py b/plugins/motd_plugin/motd_plugin.py index b45344b..f4c154b 100644 --- a/plugins/motd_plugin/motd_plugin.py +++ b/plugins/motd_plugin/motd_plugin.py @@ -28,7 +28,7 @@ def send_motd(self): #self.protocol.send_chat_message("^yellow;%s" % self._motd) if not self.config.server_name: self.config.server_name = "MY" - self.protocol.send_chat_message("^#00FFFF;WELCOME TO ^#FF0000;%s^#00FFFF; STARBOUND SERVER\n^yellow;------------------------------------------------------------------\n^green;Type: ^yellow;/help ^green;for list of available commands\n^green;Type: ^yellow;/starteritems ^green;for some starter items ^cyan;(once)\n^green;Type: ^yellow;/fuel ^green;to get your daily fuel supply ^cyan;(once a day)\n^green;Legend: ^#F7434C;Owner^yellow;, ^#C443F7;Admin^yellow;, ^#4385F7;Moderator^yellow;, ^#A0F743;Registered user^yellow;, Guest\n^yellow;------------------------------------------------------------------\n^cyan;%s" % (self.config.server_name, self._motd)) + self.protocol.send_chat_message("%s" % (self._motd)) @permissions(UserLevels.GUEST) def motd(self, data): diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 171d395..700d9a6 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -181,14 +181,19 @@ def on_entity_create(self, data): self.protocol.player.org_name, p_type) return False """ - if self.protect_everything and self.protocol.player.access_level < UserLevels.REGISTERED and not self.protocol.player.on_ship: - entities = entity_create.parse(data.data) - for entity in entities.entity: - if entity.entity_type == EntityType.PROJECTILE: - if self.block_all: return False - p_type = star_string("").parse(entity.entity) - if p_type in self.blacklist: - self.logger.info( - "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", - self.protocol.player.org_name, p_type) - return False + #if self.protect_everything and self.protocol.player.access_level < UserLevels.REGISTERED and not self.protocol.player.on_ship: + if self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.ADMIN: + name = self.protocol.player.org_name + if name in self.player_planets[self.protocol.player.planet]: + return True + else: + entities = entity_create.parse(data.data) + for entity in entities.entity: + if entity.entity_type == EntityType.PROJECTILE: + if self.block_all: return False + p_type = star_string("").parse(entity.entity) + if p_type in self.blacklist: + self.logger.info( + "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", + self.protocol.player.org_name, p_type) + return False diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 75e5a1c..02fd0cf 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -61,7 +61,6 @@ def warp_ship(self, location): def warp_self_to_player(self, name): name = " ".join(name) - #name, rest = extract_name(data) self.warp_player_to_player(self.protocol.player.name, name) def warp_player_to_player(self, from_string, to_string): @@ -73,7 +72,7 @@ def warp_player_to_player(self, from_string, to_string): if from_player is not to_player: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t="WARP_OTHER_SHIP", - player=to_player.name.encode('utf-8'))) + player=to_player.org_name.encode('utf-8'))) else: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t='WARP_UP')) From 7b3fcc904b88fa87c88700afcb92a106ba5c1745 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 4 Jan 2015 00:03:19 -0500 Subject: [PATCH 48/95] brining the development branch up to speed --- config/config.json.default | 2 +- packet_stream.py | 15 +- packets/packet_types.py | 15 +- plugins/admin_messenger/admin_messenger.py | 27 +- plugins/announcer_plugin/announcer_plugin.py | 4 +- .../admin_command_plugin.py | 249 ++++++++++++------ plugins/core/colored_names/colored_names.py | 9 +- plugins/core/player_manager/manager.py | 70 +++-- plugins/core/player_manager/plugin.py | 165 +++++++++--- .../starbound_config_manager.py | 8 +- plugins/motd_plugin/motd_plugin.py | 18 +- .../planet_protect/planet_protect_plugin.py | 159 ++++++++--- .../plugin_manager_plugin.py | 56 ++-- plugins/warpy_plugin/warpy_plugin.py | 63 +++-- server.py | 78 +++--- 15 files changed, 661 insertions(+), 277 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index f6f0406..abfcfc6 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -1,6 +1,6 @@ { - "bind_port": 21025, "bind_address": "", + "bind_port": 21025, "chat_prefix": "@", "colors": { "admin": "^#C443F7;", diff --git a/packet_stream.py b/packet_stream.py index 00151bc..979704b 100644 --- a/packet_stream.py +++ b/packet_stream.py @@ -29,7 +29,7 @@ def __init__(self, protocol): self.packet_size = None self.protocol = protocol self.direction = None - self.last_received_timestamp = datetime.datetime.utcnow() + self.last_received_timestamp = datetime.datetime.now() def __add__(self, other): self._stream += other @@ -39,7 +39,7 @@ def __add__(self, other): except: pass finally: - self.last_received_timestamp = datetime.datetime.utcnow() + self.last_received_timestamp = datetime.datetime.now() return self def start_packet(self): @@ -55,8 +55,8 @@ def start_packet(self): self.header_length = 1 + len(packets.SignedVLQ("").build(packet_header.payload_size)) self.packet_size = self.payload_size + self.header_length return True - except: - self.logger.exception("Unknown error in start_packet.") + except RuntimeError: + self.logger.error("Unknown error in start_packet.") return False def check_packet(self): @@ -88,11 +88,12 @@ def check_packet(self): self.reset() if self.start_packet(): self.check_packet() - except: - self.logger.exception("Unknown error in check_packet") + except RuntimeError: + self.logger.error("Unknown error in check_packet") + #return False def reset(self): self.id = None self.payload_size = None self.packet_size = None - self.compressed = False \ No newline at end of file + self.compressed = False diff --git a/packets/packet_types.py b/packets/packet_types.py index 6723602..92cb7f6 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -127,7 +127,7 @@ def _decode(self, obj, context): chat_sent = lambda name="chat_sent": Struct(name, star_string("message"), - Padding(1)) + Byte("chat_channel")) client_connect = lambda name="client_connect": Struct(name, VLQ("asset_digest_length"), @@ -222,6 +222,13 @@ def _decode(self, obj, context): Byte("entity_type"), VLQ("entity_size"), String("entity", lambda ctx: ctx.entity_size), - SignedVLQ("entity_id") - ))) -projectile = DictVariant("projectile") \ No newline at end of file + SignedVLQ("entity_id")))) + +client_context_update = lambda name="client_context": Struct(name, + VLQ("length"), + Byte("arguments"), + Array(lambda ctx: ctx.arguments, + Struct("key", + Variant("value")))) + +projectile = DictVariant("projectile") diff --git a/plugins/admin_messenger/admin_messenger.py b/plugins/admin_messenger/admin_messenger.py index 189263e..42b7339 100644 --- a/plugins/admin_messenger/admin_messenger.py +++ b/plugins/admin_messenger/admin_messenger.py @@ -1,10 +1,11 @@ from base_plugin import BasePlugin from plugins.core.player_manager import permissions, UserLevels import packets +from datetime import datetime class AdminMessenger(BasePlugin): - """Adds support to message moderators/admins/owner with a ## prefixed message.""" + """Adds support to message moderators/admins/owner with a @@ prefixed message.""" name = "admin_messenger" depends = ['player_manager'] auto_activate = True @@ -24,18 +25,28 @@ def on_chat_sent(self, data): return True def message_admins(self, message): + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^red;<" + now.strftime("%H:%M") + "> ^yellow;" + else: + timestamp = "" for protocol in self.factory.protocols.itervalues(): if protocol.player.access_level >= UserLevels.MODERATOR: - protocol.send_chat_message( - _("Received an admin message from %s: %s.") % (self.protocol.player.name, - message.message[2:])) + protocol.send_chat_message(timestamp + + "%sADMIN: ^yellow;<%s^yellow;> %s%s" % (self.config.colors["moderator"], self.protocol.player.colored_name(self.config.colors), + self.config.colors["moderator"],message.message[2:].decode("utf-8"))) self.logger.info("Received an admin message from %s. Message: %s", self.protocol.player.name, - message.message[2:]) + message.message[2:].decode("utf-8")) @permissions(UserLevels.ADMIN) def broadcast_message(self, message): + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^red;<" + now.strftime("%H:%M") + "> " + else: + timestamp = "" for protocol in self.factory.protocols.itervalues(): - protocol.send_chat_message(_("%sSERVER BROADCAST: %s%s") % ( - self.config.colors["admin"], message.message[3:], self.config.colors["default"])) + protocol.send_chat_message(timestamp + "%sBROADCAST: ^red;%s%s" % ( + self.config.colors["admin"], message.message[3:].decode("utf-8").upper(), self.config.colors["default"])) self.logger.info("Broadcast from %s. Message: %s", self.protocol.player.name, - message.message[3:]) + message.message[3:].decode("utf-8").upper()) diff --git a/plugins/announcer_plugin/announcer_plugin.py b/plugins/announcer_plugin/announcer_plugin.py index f681ee8..2dd2927 100644 --- a/plugins/announcer_plugin/announcer_plugin.py +++ b/plugins/announcer_plugin/announcer_plugin.py @@ -17,7 +17,7 @@ def after_connect_response(self, data): c = connect_response().parse(data.data) if c.success: self.factory.broadcast( - self.protocol.player.colored_name(self.config.colors) + " joined.", 0, "", "Announcer") + self.protocol.player.colored_name(self.config.colors) + " logged in.", 0, "", "Announcer") except AttributeError: self.logger.debug("Attribute error in after_connect_response.") return @@ -27,6 +27,6 @@ def after_connect_response(self, data): def on_client_disconnect(self, data): if self.protocol.player is not None: - self.factory.broadcast(self.protocol.player.colored_name(self.config.colors) + " left.", 0, + self.factory.broadcast(self.protocol.player.colored_name(self.config.colors) + " logged out.", 0, "", "Announcer") diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 7171089..d2a9afe 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -13,8 +13,8 @@ class UserCommandPlugin(SimpleCommandPlugin): """ name = "user_management_commands" depends = ['command_dispatcher', 'player_manager'] - commands = ["who", "whois", "promote", "kick", "ban", "give_item", "planet", "mute", "unmute", - "passthrough", "shutdown", "bans"] + commands = ["who", "whoami", "whois", "promote", "kick", "ban", "ban_list", "unban", "item", + "planet", "mute", "unmute", "passthrough", "shutdown", "timestamps"] auto_activate = True def activate(self): @@ -23,35 +23,53 @@ def activate(self): @permissions(UserLevels.GUEST) def who(self, data): - __doc__ = _("""Returns all current users on the server. Syntax: /who""") + """Displays all current players on the server.\nSyntax: /who""" who = [w.colored_name(self.config.colors) for w in self.player_manager.who()] - self.protocol.send_chat_message("_(%d players online: %s)" % (len(who), ", ".join(who))) + self.protocol.send_chat_message("^cyan;%d^green; players online: %s" % (len(who), ", ".join(who))) return False @permissions(UserLevels.GUEST) def planet(self, data): - __doc__ = _("""Displays who is on your current planet.""") + """Displays who is on your current planet.\nSyntax: /planet""" who = [w.colored_name(self.config.colors) for w in self.player_manager.who() if w.planet == self.protocol.player.planet and not w.on_ship] - self.protocol.send_chat_message(_("%d players on your current planet: %s") % (len(who), ", ".join(who))) + self.protocol.send_chat_message("^cyan;%d^green; players on planet: %s" % (len(who), ", ".join(who))) - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.GUEST) + def whoami(self, data): + """Displays client data about yourself.\nSyntax: /whoami""" + info = self.protocol.player + self.protocol.send_chat_message( + "Name: %s ^green;: ^gray;%s\nUserlevel: ^yellow;%s^green; (^gray;%s^green;)\nUUID: ^yellow;%s^green;\nIP address: ^cyan;%s^green;\nCurrent planet: ^yellow;%s^green;" % ( + info.colored_name(self.config.colors), info.org_name, UserLevels(info.access_level), + info.last_seen.strftime("%c"), info.uuid, info.ip, info.planet)) + return False + + @permissions(UserLevels.REGISTERED) def whois(self, data): - __doc__ = _("""Returns client data about the specified user. Syntax: /whois [user name]""") - name = " ".join(data) + """Displays client data about the specified user.\nSyntax: /whois (player)""" + if len(data) == 0: + self.protocol.send_chat_message(self.whois.__doc__) + return + name, garbage = extract_name(data) info = self.player_manager.whois(name) - if info: + if info and self.protocol.player.access_level >= UserLevels.ADMIN: + self.protocol.send_chat_message( + "Name: %s ^green;: ^gray;%s\nUserlevel: ^yellow;%s^green; (^gray;%s^green;)\nUUID: ^yellow;%s^green;\nIP address: ^cyan;%s^green;\nCurrent planet: ^yellow;%s^green;" % ( + info.colored_name(self.config.colors), info.org_name, UserLevels(info.access_level), + info.last_seen.strftime("%c"), info.uuid, info.ip, info.planet)) + elif info: self.protocol.send_chat_message( - _("Name: %s\nUserlevel: %s\nUUID: %s\nIP address: %s\nCurrent planet: %s""") % ( - info.colored_name(self.config.colors), UserLevels(info.access_level), info.uuid, info.ip, - info.planet)) + "Name: %s ^green;: ^gray;%s\nUserlevel: ^yellow;%s^green;\nLast seen: ^gray;%s" % ( + info.colored_name(self.config.colors), info.org_name, UserLevels(info.access_level), + info.last_seen.strftime("%c"))) else: - self.protocol.send_chat_message(_("Player not found!")) + self.protocol.send_chat_message("Player not found!") return False @permissions(UserLevels.MODERATOR) def promote(self, data): - __doc__ = _("""Promotes/demotes a user to a specific rank. Syntax: /promote [username] [rank] (where rank is either: registered, moderator, admin, or guest))""") + """Promotes/demotes a player to a specific rank.\nSyntax: /promote (player) (rank) (where rank is either: guest, registered, moderator, admin, or owner)""" self.logger.trace("Promote command received with the following data: %s" % ":".join(data)) if len(data) > 0: name = " ".join(data[:-1]) @@ -65,13 +83,24 @@ def promote(self, data): for line in pprint.pformat(player).split("\n"): self.logger.trace("\t" + line) old_rank = player.access_level - if old_rank >= self.protocol.player.access_level: + players = self.player_manager.all() + if old_rank == 1000: + owner_count = 0 + for aclvl in players: + if aclvl.access_level == old_rank: + owner_count += 1 + if owner_count <= 1: + self.protocol.send_chat_message("You are the only (or last) owner. Promote denied!") + return + if old_rank >= self.protocol.player.access_level and not self.protocol.player.access_level != UserLevels.ADMIN: self.logger.trace( "The old rank was greater or equal to the current rank. Sending a message and returning.") self.protocol.send_chat_message( - _("You cannot change that user's access level as they are at least at an equal level as you.")) + "You cannot change that user's access level as they are at least at an equal level as you.") return - if rank == "admin": + if rank == "owner": + self.make_owner(player) + elif rank == "admin": self.make_admin(player) elif rank == "moderator": self.make_mod(player) @@ -81,23 +110,23 @@ def promote(self, data): self.make_guest(player) else: self.logger.trace("Non-existent rank. Returning with a help message.") - self.protocol.send_chat_message(_("No such rank!\n") + self.promote.__doc__) + self.protocol.send_chat_message("No such rank!\n" + self.promote.__doc__) return self.logger.trace("Sending promotion message to promoter.") - self.protocol.send_chat_message(_("%s: %s -> %s") % ( + self.protocol.send_chat_message("%s: %s -> %s" % ( player.colored_name(self.config.colors), UserLevels(old_rank), rank.upper())) self.logger.trace("Sending promotion message to promoted player.") try: self.factory.protocols[player.protocol].send_chat_message( - _("%s has promoted you to %s") % ( + "%s has promoted you to %s" % ( self.protocol.player.colored_name(self.config.colors), rank.upper())) except KeyError: - self.logger.trace("Promoted player is not logged in.") + self.logger.info("Promoted player is not logged in.") else: self.logger.trace("Player wasn't found. Sending chat message to player.") - self.protocol.send_chat_message(_("Player not found!\n") + self.promote.__doc__) + self.protocol.send_chat_message("Player not found!\n" + self.promote.__doc__) return else: self.logger.trace("Received blank promotion command. Sending help message.") @@ -123,83 +152,128 @@ def make_admin(self, player): self.logger.trace("Setting %s to ADMIN", player.name) player.access_level = UserLevels.ADMIN + @permissions(UserLevels.OWNER) + def make_owner(self, player): + player.access_level = UserLevels.OWNER + @permissions(UserLevels.MODERATOR) def kick(self, data): - __doc__ = _("""Kicks a user from the server. Usage: /kick [username] [reason]""") + """Kicks a user from the server.\nSyntax: /kick (player) [reason]""" + if len(data) == 0: + self.protocol.send_chat_message(self.kick.__doc__) + return name, reason = extract_name(data) - if reason is None: - reason = "no reason given" + if not reason: + reason = ["no reason given"] else: reason = " ".join(reason) info = self.player_manager.whois(name) if info and info.logged_in: - tp = self.factory.protocols[info.protocol] - tp.transport.loseConnection() - self.factory.broadcast("%s kicked %s (reason: %s)" % - (self.protocol.player.name, - info.name, - reason)) + self.factory.broadcast("%s^green; kicked %s ^green;(reason: ^yellow;%s^green;)" % + (self.protocol.player.colored_name(self.config.colors), + info.colored_name(self.config.colors), + " ".join(reason))) self.logger.info("%s kicked %s (reason: %s)", self.protocol.player.name, info.name, - reason) + " ".join(reason)) + tp = self.factory.protocols[info.protocol] + tp.die() else: - self.protocol.send_chat_message(_("Couldn't find a user by the name %s.") % name) + self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;." % name) return False @permissions(UserLevels.ADMIN) def ban(self, data): - __doc__ = _("""Bans an IP (retrieved by /whois). Syntax: /ban [ip address]""") + """Bans an IP or a Player (by name).\nSyntax: /ban (IP | player)\nTip: Use /whois (player) to get IP""" + if len(data) == 0: + self.protocol.send_chat_message(self.ban.__doc__) + return try: ip = data[0] + socket.inet_aton(ip) print socket.inet_aton(ip) self.logger.debug("Banning IP address %s" % ip) self.player_manager.ban(ip) - self.protocol.send_chat_message(_("Banned IP: %s") % ip) + self.protocol.send_chat_message("Banned IP: ^red;%s^green;" % ip) self.logger.warning("%s banned IP: %s", self.protocol.player.name, ip) return False except socket.error: self.ban_by_name(data) return False - def ban_by_name(self, data): - raise NotImplementedError - - @permissions(UserLevels.ADMIN) - def bans(self, data): - __doc__ = _("""Lists the currently banned IPs. Syntax: /bans""") - self.protocol.send_chat_message("\n".join( - [_("IP: %s ") % x.ip for x in self.player_manager.bans])) + def ban_list(self, data): + """Displays the currently banned IPs.\nSyntax: /ban_list""" + res = self.player_manager.list_bans() + if res: + self.protocol.send_chat_message("Banned list (IPs and Names):") + for banned in res: + try: + socket.inet_aton(banned.ip) + self.protocol.send_chat_message( + "IP: ^red;%s ^green;Reason: ^yellow;%s^green;" % (banned.ip, banned.reason)) + except: + self.protocol.send_chat_message( + "Player: ^red;%s ^green;Reason: ^yellow;%s^green;" % ( + self.player_manager.get_by_org_name(banned.ip).name, banned.reason)) + else: + self.protocol.send_chat_message("No bans found.") @permissions(UserLevels.ADMIN) def unban(self, data): - __doc__ = _("""Unbans an IP. Syntax: /unban [ip address]""") - ip = data[0] - for ban in self.player_manager.bans: - if ban.ip == ip: - self.player_manager.remove_ban(ban) - self.protocol.send_chat_message(_("Unbanned IP: %s") % ip) - break + """Unbans an IP or a Player (by name).\nSyntax: /unban (IP | player)""" + if len(data) == 0: + self.protocol.send_chat_message(self.unban.__doc__) + return + try: + ip = data[0] + socket.inet_aton(ip) + self.player_manager.unban(ip) + self.protocol.send_chat_message("Unbanned IP: ^yellow;%s^green;" % ip) + self.logger.warning("%s unbanned IP: %s", self.protocol.player.name, ip) + return False + except socket.error: + self.unban_by_name(data) + return False + + def ban_by_name(self, data): + name, reason = extract_name(data) + info = self.player_manager.get_by_name(name) + if info: + self.player_manager.ban(info.org_name) + self.protocol.send_chat_message("Banned: %s" % info.colored_name(self.config.colors)) + self.logger.warning("%s banned player: %s", self.protocol.player.org_name, info.org_name) else: - self.protocol.send_chat_message(_("Couldn't find IP: %s") % ip) + self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;." % name) + return False + + def unban_by_name(self, data): + name, reason = extract_name(data) + info = self.player_manager.get_by_name(name) + if info: + self.player_manager.unban(info.org_name) + self.protocol.send_chat_message("Unbanned: %s" % info.colored_name(self.config.colors)) + self.logger.warning("%s unbanned: %s", self.protocol.player.org_name, info.org_name) + else: + self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;." % name) return False @permissions(UserLevels.ADMIN) - def give_item(self, data): - __doc__ = _("""Gives an item to a player. Syntax: /give [target player] [item name] [optional: item count]""") + def item(self, data): + """Gives an item to a player.\nSyntax: /item (player) (item) [count]""" if len(data) >= 2: try: name, item = extract_name(data) except ValueError as e: - self.protocol.send_chat_message(_("Please check your syntax. %s") % str(e)) + self.protocol.send_chat_message("Please check your syntax. %s" % str(e)) return except AttributeError: self.protocol.send_chat_message( - _("Please check that the username you are referencing exists. If it has spaces, please surround it by quotes.")) + "Please check that the username you are referencing exists. If it has spaces, please surround it by quotes.") return except: - self.protocol.send_chat_message(_("An unknown error occured. %s") % str(e)) + self.protocol.send_chat_message("An unknown error occured. %s" % str(e)) target_player = self.player_manager.get_logged_in_by_name(name) target_protocol = self.factory.protocols[target_player.protocol] if target_player is not None: @@ -211,61 +285,77 @@ def give_item(self, data): item_count = 1 give_item_to_player(target_protocol, item_name, item_count) target_protocol.send_chat_message( - _("%s has given you: %s (count: %s)") % ( - self.protocol.player.name, item_name, item_count)) - self.protocol.send_chat_message(_("Sent the item(s).")) + "%s^green; has given you: ^yellow;%s^green; (count: ^cyan;%s^green;)" % ( + self.protocol.player.colored_name(self.config.colors), item_name, item_count)) + self.protocol.send_chat_message("Sent ^yellow;%s^green; (count: ^cyan;%s^green;) to %s" % ( + item_name, item_count, target_player.colored_name(self.config.colors))) self.logger.info("%s gave %s %s (count: %s)", self.protocol.player.name, name, item_name, item_count) else: - self.protocol.send_chat_message(_("You have to give an item name.")) + self.protocol.send_chat_message("You have to give an item name.") else: - self.protocol.send_chat_message(_("Couldn't find name: %s" % name)) + self.protocol.send_chat_message("Couldn't find name: ^yellow;%s^green;" % name) return False else: - self.protocol.send_chat_message(self.give_item.__doc__) + self.protocol.send_chat_message(self.item.__doc__) @permissions(UserLevels.MODERATOR) def mute(self, data): - __doc__ = _("""Mute a player. Syntax: /mute [player name]""") - name = " ".join(data) + """Mute a player.\nSyntax: /mute (player)""" + name, garbage = extract_name(data) player = self.player_manager.get_logged_in_by_name(name) if player is None: - self.protocol.send_chat_message("Couldn't find a user by the name %s" % name) + self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;" % name) return target_protocol = self.factory.protocols[player.protocol] player.muted = True - target_protocol.send_chat_message(_("You have been muted.")) - self.protocol.send_chat_message(_("%s has been muted.") % name) + target_protocol.send_chat_message("You have been ^red;muted^green;.") + self.protocol.send_chat_message( + "%s^green; has been ^red;muted^green;." % target_protocol.player.colored_name(self.config.colors)) @permissions(UserLevels.MODERATOR) def unmute(self, data): - __doc__ = _("""Unmute a currently muted player. Syntax: /unmute [player name]""") - name = " ".join(data) + """Unmute a currently muted player.\nSyntax: /unmute (player)""" + name, garbage = extract_name(data) player = self.player_manager.get_logged_in_by_name(name) if player is None: - self.protocol.send_chat_message(_("Couldn't find a user by the name %s") % name) + self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;" % name) return target_protocol = self.factory.protocols[player.protocol] player.muted = False - target_protocol.send_chat_message(_("You have been unmuted.")) - self.protocol.send_chat_message(_("%s has been unmuted.") % name) + target_protocol.send_chat_message("You have been ^yellow;unmuted^green;.") + self.protocol.send_chat_message( + "%s^green; has been ^yellow;unmuted^green;." % target_protocol.player.colored_name(self.config.colors)) @permissions(UserLevels.ADMIN) def passthrough(self, data): - __doc__ = _("""Sets the server to passthrough mode. *This is irreversible without restart.* Syntax: /passthrough""") + """Sets the server to passthrough mode.\nSyntax: /passthrough\n^red;This is irreversible without stopping the wrapper, changing config.json and restarting!""" self.config.passthrough = True @permissions(UserLevels.ADMIN) def shutdown(self, data): - __doc__ = _("""Shutdown the server in n seconds. Syntax: /shutdown [number of seconds] (>0)""") + """Shutdown the server in n seconds.\nSyntax: /shutdown (seconds) (>0)""" try: x = float(data[0]) except ValueError: - self.protocol.send_chat_message(_("%s is not a number. Please enter a value in seconds.") % data[0]) + self.protocol.send_chat_message( + "^yellow;%s^green; is not a number. Please enter a value in seconds." % data[0]) return - self.factory.broadcast(_("SERVER ANNOUNCEMENT: Server is shutting down in %s seconds!") % data[0]) + self.factory.broadcast( + "SERVER ANNOUNCEMENT: ^red;Server is shutting down in ^yellow;%s^red; seconds!^green;" % data[0]) reactor.callLater(x, reactor.stop) + @permissions(UserLevels.OWNER) + def timestamps(self, data): + """Toggles chat time stamps.\nSyntax: /timestamps""" + if self.config.chattimestamps: + self.config.chattimestamps = False + self.factory.broadcast("Chat timestamps are now ^red;HIDDEN") + + else: + self.config.chattimestamps = True + self.factory.broadcast("Chat timestamps are now ^yellow;SHOWN") + class MuteManager(BasePlugin): name = "mute_manager" @@ -273,9 +363,10 @@ class MuteManager(BasePlugin): def on_chat_sent(self, data): data = chat_sent().parse(data.data) if self.protocol.player.muted and data.message[0] != self.config.command_prefix and data.message[ - :2] != self.config.chat_prefix*2: + :2] != self.config.chat_prefix * 2: self.protocol.send_chat_message( - _("You are currently muted and cannot speak. You are limited to commands and admin chat (prefix your lines with %s for admin chat.") % (self.config.chat_prefix*2)) + "You are currently ^red;muted^green; and cannot speak. You are limited to commands and admin chat (prefix your lines with ^yellow;%s^green; for admin chat." % ( + self.config.chat_prefix * 2)) return False return True diff --git a/plugins/core/colored_names/colored_names.py b/plugins/core/colored_names/colored_names.py index d9df066..294a393 100644 --- a/plugins/core/colored_names/colored_names.py +++ b/plugins/core/colored_names/colored_names.py @@ -1,6 +1,7 @@ from base_plugin import BasePlugin from packets.packet_types import chat_received, Packets from utility_functions import build_packet +from datetime import datetime class ColoredNames(BasePlugin): @@ -16,12 +17,16 @@ def activate(self): self.player_manager = self.plugins['player_manager'].player_manager def on_chat_received(self, data): + now = datetime.now() try: p = chat_received().parse(data.data) if p.name == "server": return - sender = self.player_manager.get_logged_in_by_name(p.name) - p.name = sender.colored_name(self.config.colors) + sender = self.player_manager.get_by_org_name(str(p.name)) + if self.config.chattimestamps: + p.name = now.strftime("%H:%M") + "> <" + sender.colored_name(self.config.colors) + else: + p.name = sender.colored_name(self.config.colors) self.protocol.transport.write(build_packet(Packets.CHAT_RECEIVED, chat_received().build(p))) except AttributeError as e: self.logger.warning("Received AttributeError in colored_name. %s", str(e)) diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index bfa0bda..7ed0b53 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -4,6 +4,7 @@ import inspect import logging import json +import sqlite3 from enum import Enum from sqlalchemy.ext.mutable import Mutable @@ -147,6 +148,7 @@ class Player(Base): uuid = Column(String, primary_key=True) name = Column(String) + org_name = Column(String) last_seen = Column(DateTime) access_level = Column(Integer) logged_in = Column(Boolean) @@ -210,11 +212,12 @@ class Ban(Base): class PlayerManager(object): def __init__(self, config): self.config = config + logger.info("Loading player database.") self.engine = create_engine('sqlite:///%s' % path.preauthChild(self.config.player_db).path) Base.metadata.create_all(self.engine) self.sessionmaker = sessionmaker(bind=self.engine, autoflush=True) with _autoclosing_session(self.sessionmaker) as session: - for player in session.query(Player).all(): + for player in session.query(Player).filter_by(logged_in=True).all(): player.logged_in = False player.protocol = None session.commit() @@ -234,27 +237,33 @@ def _cache_and_return_from_session(self, session, record, collection=False): return to_return - def fetch_or_create(self, uuid, name, ip, protocol=None): + def fetch_or_create(self, uuid, name, org_name, ip, protocol=None): with _autoclosing_session(self.sessionmaker) as session: if session.query(Player).filter_by(uuid=uuid, logged_in=True).first(): raise AlreadyLoggedIn if self.check_bans(ip): raise Banned - while self.whois(name): - logger.info("Got a duplicate player, affixing _ to name") + if self.check_bans(org_name): + raise Banned + while (self.get_by_name(name) and not self.get_by_org_name(org_name)) or ( + self.get_by_name(name) and self.get_by_org_name(org_name) and self.get_by_name( + name).uuid != self.get_by_org_name(org_name).uuid): + logger.info("Got a duplicate nickname, affixing _ to name") name += "_" player = session.query(Player).filter_by(uuid=uuid).first() if player: if player.name != name: logger.info("Detected username change.") player.name = name + self.protocol.player.name = name if ip not in player.ips: player.ips.append(IPAddress(ip=ip)) player.ip = ip player.protocol = protocol + player.last_seen = datetime.datetime.now() else: logger.info("Adding new player with name: %s" % name) - player = Player(uuid=uuid, name=name, + player = Player(uuid=uuid, name=name, org_name=org_name, last_seen=datetime.datetime.now(), access_level=int(UserLevels.GUEST), logged_in=False, @@ -283,7 +292,7 @@ def who(self): session, session.query(Player).filter_by(logged_in=True).all(), collection=True, - ) + ) def all(self): with _autoclosing_session(self.sessionmaker) as session: @@ -291,7 +300,7 @@ def all(self): session, session.query(Player).all(), collection=True, - ) + ) def all_like(self, regex): with _autoclosing_session(self.sessionmaker) as session: @@ -299,22 +308,29 @@ def all_like(self, regex): session, session.query(Player).filter(Player.name.like(regex)).all(), collection=True, - ) + ) def whois(self, name): with _autoclosing_session(self.sessionmaker) as session: - return self._cache_and_return_from_session( - session, - session.query(Player).filter( - Player.logged_in, - func.lower(Player.name) == func.lower(name), - ).first(), - ) + return session.query(Player).filter(func.lower(Player.name) == func.lower(name)).first() + + def list_bans(self): + with _autoclosing_session(self.sessionmaker) as session: + return session.query(Ban).all() def check_bans(self, ip): with _autoclosing_session(self.sessionmaker) as session: return session.query(Ban).filter_by(ip=ip).first() is not None + def unban(self, ip): + with _autoclosing_session(self.sessionmaker) as session: + res = session.query(Ban).filter_by(ip=ip).first() + if res == None: + #self.protocol.send_chat_message(self.user_management_commands.unban.__doc__) + return + session.delete(res) + session.commit() + def ban(self, ip): with _autoclosing_session(self.sessionmaker) as session: session.add(Ban(ip=ip)) @@ -326,7 +342,7 @@ def bans(self): return self._cache_and_return_from_session( session, session.query(Ban).all(), - ) + ) def delete_ban(self, ban_cache): with _autoclosing_session(self.sessionmaker) as session: @@ -338,7 +354,21 @@ def get_by_name(self, name): return self._cache_and_return_from_session( session, session.query(Player).filter(func.lower(Player.name) == func.lower(name)).first(), - ) + ) + + def get_by_org_name(self, org_name): + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter(func.lower(Player.org_name) == func.lower(org_name)).first(), + ) + + def get_by_uuid(self, uuid): + with _autoclosing_session(self.sessionmaker) as session: + return self._cache_and_return_from_session( + session, + session.query(Player).filter(func.lower(Player.uuid) == func.lower(uuid)).first(), + ) def get_logged_in_by_name(self, name): with _autoclosing_session(self.sessionmaker) as session: @@ -347,8 +377,8 @@ def get_logged_in_by_name(self, name): session.query(Player).filter( Player.logged_in, func.lower(Player.name) == func.lower(name), - ).first(), - ) + ).first(), + ) def permissions(level=UserLevels.OWNER): @@ -362,7 +392,7 @@ def wrapped_function(self, *args, **kwargs): if self.protocol.player.access_level >= level: return f(self, *args, **kwargs) else: - self.protocol.send_chat_message(_("You are not an admin.")) + self.protocol.send_chat_message("You are not authorized to do this.") return False return wrapped_function diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index cab6804..7122c9b 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -1,3 +1,4 @@ +import base64 import re from construct import Container @@ -6,14 +7,14 @@ from base_plugin import SimpleCommandPlugin from manager import PlayerManager, Banned, Player, permissions, UserLevels -from packets import client_connect, connect_response +from packets import client_connect, connect_response, warp_command import packets -from utility_functions import build_packet, Planet +from utility_functions import extract_name, build_packet, Planet class PlayerManagerPlugin(SimpleCommandPlugin): name = "player_manager" - commands = ["list_players", "delete_player"] + commands = ["player_list", "player_delete", "nick", "nick_set"] def activate(self): super(PlayerManagerPlugin, self).activate() @@ -33,20 +34,40 @@ def check_logged_in(self): def on_client_connect(self, data): client_data = client_connect().parse(data.data) try: - original_name = client_data.name - for regex in self.regexes: - client_data.name = re.sub(regex, "", client_data.name) + changed_name = client_data.name + for regex in self.regexes: # Replace problematic chars in client name + changed_name = re.sub(regex, "", changed_name) + if len(client_data.name.strip()) == 0: # If the username is nothing but spaces. raise NameError("Your name must not be empty!") - if client_data.name != original_name: + + if client_data.name != changed_name: # Logging changed username self.logger.info("Player tried to log in with name %s, replaced with %s.", - original_name, client_data.name) + client_data.name, changed_name) + + changed_player = self.player_manager.get_by_uuid(client_data.uuid) + if changed_player is not None and changed_player.name != changed_name: + self.logger.info("Got player with changed nickname. Fetching nickname!") + changed_name = changed_player.name + + duplicate_player = self.player_manager.get_by_org_name(client_data.name) + if duplicate_player is not None and duplicate_player.uuid != client_data.uuid: + raise NameError( + "The name of this character is already taken on the server!\nPlease, create a new character with a different name or use Starcheat and change the name.") + self.logger.info("Got a duplicate original player name, asking player to change character name!") + #rnd_append = str(randrange(10, 99)) + #original_name += rnd_append + #client_data.name += rnd_append + + original_name = client_data.name + client_data.name = changed_name self.protocol.player = self.player_manager.fetch_or_create( name=client_data.name, + org_name=original_name, uuid=str(client_data.uuid), ip=self.protocol.transport.getPeer().host, protocol=self.protocol.id, - ) + ) return True except AlreadyLoggedIn: @@ -61,6 +82,9 @@ def on_client_connect(self, data): self.reject_with_reason(str(e)) def reject_with_reason(self, reason): + # here there be magic... ask Carrots or Teihoo about this... + magic_sector = "AQAAAAwAAAAy+gofAAX14QD/Z2mAAJiWgAUFYWxwaGEMQWxwaGEgU2VjdG9yAAAAELIfhbMFQWxwaGEHAgt0aHJlYXRMZXZlbAYCBAIEAg51bmxvY2tlZEJpb21lcwYHBQRhcmlkBQZkZXNlcnQFBmZvcmVzdAUEc25vdwUEbW9vbgUGYmFycmVuBQ1hc3Rlcm9pZGZpZWxkBwcCaWQFBWFscGhhBG5hbWUFDEFscGhhIFNlY3RvcgpzZWN0b3JTZWVkBISWofyWZgxzZWN0b3JTeW1ib2wFFy9jZWxlc3RpYWwvc2VjdG9yLzEucG5nCGh1ZVNoaWZ0BDsGcHJlZml4BQVBbHBoYQ93b3JsZFBhcmFtZXRlcnMHAgt0aHJlYXRMZXZlbAYCBAIEAg51bmxvY2tlZEJpb21lcwYHBQRhcmlkBQZkZXNlcnQFBmZvcmVzdAUEc25vdwUEbW9vbgUGYmFycmVuBQ1hc3Rlcm9pZGZpZWxkBGJldGELQmV0YSBTZWN0b3IAAADUWh1fvwRCZXRhBwILdGhyZWF0TGV2ZWwGAgQEBAQOdW5sb2NrZWRCaW9tZXMGCQUEYXJpZAUGZGVzZXJ0BQhzYXZhbm5haAUGZm9yZXN0BQRzbm93BQRtb29uBQZqdW5nbGUFBmJhcnJlbgUNYXN0ZXJvaWRmaWVsZAcHAmlkBQRiZXRhBG5hbWUFC0JldGEgU2VjdG9yCnNlY3RvclNlZWQEtYuh6v5+DHNlY3RvclN5bWJvbAUXL2NlbGVzdGlhbC9zZWN0b3IvMi5wbmcIaHVlU2hpZnQEAAZwcmVmaXgFBEJldGEPd29ybGRQYXJhbWV0ZXJzBwILdGhyZWF0TGV2ZWwGAgQEBAQOdW5sb2NrZWRCaW9tZXMGCQUEYXJpZAUGZGVzZXJ0BQhzYXZhbm5haAUGZm9yZXN0BQRzbm93BQRtb29uBQZqdW5nbGUFBmJhcnJlbgUNYXN0ZXJvaWRmaWVsZAVnYW1tYQxHYW1tYSBTZWN0b3IAAADMTMw79wVHYW1tYQcCC3RocmVhdExldmVsBgIEBgQGDnVubG9ja2VkQmlvbWVzBgoFBGFyaWQFBmRlc2VydAUIc2F2YW5uYWgFBmZvcmVzdAUEc25vdwUEbW9vbgUGanVuZ2xlBQpncmFzc2xhbmRzBQZiYXJyZW4FDWFzdGVyb2lkZmllbGQHBwJpZAUFZ2FtbWEEbmFtZQUMR2FtbWEgU2VjdG9yCnNlY3RvclNlZWQEs4nM4e9uDHNlY3RvclN5bWJvbAUXL2NlbGVzdGlhbC9zZWN0b3IvMy5wbmcIaHVlU2hpZnQEPAZwcmVmaXgFBUdhbW1hD3dvcmxkUGFyYW1ldGVycwcCC3RocmVhdExldmVsBgIEBgQGDnVubG9ja2VkQmlvbWVzBgoFBGFyaWQFBmRlc2VydAUIc2F2YW5uYWgFBmZvcmVzdAUEc25vdwUEbW9vbgUGanVuZ2xlBQpncmFzc2xhbmRzBQZiYXJyZW4FDWFzdGVyb2lkZmllbGQFZGVsdGEMRGVsdGEgU2VjdG9yAAAA1Ooj2GcFRGVsdGEHAgt0aHJlYXRMZXZlbAYCBAgECA51bmxvY2tlZEJpb21lcwYOBQRhcmlkBQZkZXNlcnQFCHNhdmFubmFoBQZmb3Jlc3QFBHNub3cFBG1vb24FBmp1bmdsZQUKZ3Jhc3NsYW5kcwUFbWFnbWEFCXRlbnRhY2xlcwUGdHVuZHJhBQh2b2xjYW5pYwUGYmFycmVuBQ1hc3Rlcm9pZGZpZWxkBwcCaWQFBWRlbHRhBG5hbWUFDERlbHRhIFNlY3RvcgpzZWN0b3JTZWVkBLWdop7hTgxzZWN0b3JTeW1ib2wFFy9jZWxlc3RpYWwvc2VjdG9yLzQucG5nCGh1ZVNoaWZ0BHgGcHJlZml4BQVEZWx0YQ93b3JsZFBhcmFtZXRlcnMHAgt0aHJlYXRMZXZlbAYCBAgECA51bmxvY2tlZEJpb21lcwYOBQRhcmlkBQZkZXNlcnQFCHNhdmFubmFoBQZmb3Jlc3QFBHNub3cFBG1vb24FBmp1bmdsZQUKZ3Jhc3NsYW5kcwUFbWFnbWEFCXRlbnRhY2xlcwUGdHVuZHJhBQh2b2xjYW5pYwUGYmFycmVuBQ1hc3Rlcm9pZGZpZWxkB3NlY3RvcngIWCBTZWN0b3IAAABjhzJHNwFYBwILdGhyZWF0TGV2ZWwGAgQKBBQOdW5sb2NrZWRCaW9tZXMGDgUEYXJpZAUGZGVzZXJ0BQhzYXZhbm5haAUGZm9yZXN0BQRzbm93BQRtb29uBQZqdW5nbGUFCmdyYXNzbGFuZHMFBW1hZ21hBQl0ZW50YWNsZXMFBnR1bmRyYQUIdm9sY2FuaWMFBmJhcnJlbgUNYXN0ZXJvaWRmaWVsZAcIAmlkBQdzZWN0b3J4BG5hbWUFCFggU2VjdG9yCnNlY3RvclNlZWQEmPDzkpxuDHNlY3RvclN5bWJvbAUXL2NlbGVzdGlhbC9zZWN0b3IveC5wbmcIaHVlU2hpZnQEgTQIcHZwRm9yY2UDAQZwcmVmaXgFAVgPd29ybGRQYXJhbWV0ZXJzBwILdGhyZWF0TGV2ZWwGAgQKBBQOdW5sb2NrZWRCaW9tZXMGDgUEYXJpZAUGZGVzZXJ0BQhzYXZhbm5haAUGZm9yZXN0BQRzbm93BQRtb29uBQZqdW5nbGUFCmdyYXNzbGFuZHMFBW1hZ21hBQl0ZW50YWNsZXMFBnR1bmRyYQUIdm9sY2FuaWMFBmJhcnJlbgUNYXN0ZXJvaWRmaWVsZA==" + unlocked_sector_magic = base64.decodestring(magic_sector.encode("ascii")) rejection = build_packet( packets.Packets.CONNECT_RESPONSE, packets.connect_response().build( @@ -69,7 +93,7 @@ def reject_with_reason(self, reason): client_id=0, reject_reason=reason ) - ) + ) + unlocked_sector_magic ) self.protocol.transport.write(rejection) self.protocol.transport.loseConnection() @@ -91,21 +115,20 @@ def on_connect_response(self, data): return True def after_world_start(self, data): - world_start = packets.world_start().parse(data.data) - if 'fuel.max' in world_start['world_properties']: - self.logger.info("Player %s is now on a ship.", self.protocol.player.name) - self.protocol.player.on_ship = True - else: - coords = world_start.planet['celestialParameters']['coordinate'] - parent_system = coords - location = parent_system['location'] - l = location - self.protocol.player.on_ship = False - planet = Planet(parent_system['sector'], l[0], l[1], l[2], - coords['planet'], coords['satellite']) - self.protocol.player.planet = str(planet) - self.logger.info("Player %s is now at planet: %s", self.protocol.player.name, str(planet)) - + world_start = packets.world_start().parse(data.data) + if 'fuel.max' in world_start['world_properties']: + self.logger.info("Player %s is now on a ship.", self.protocol.player.name) + self.protocol.player.on_ship = True + self.protocol.player.planet = "On ship" + else: + coords = world_start.planet['celestialParameters']['coordinate'] + parent_system = coords + location = parent_system['location'] + l = location + self.protocol.player.on_ship = False + planet = Planet(parent_system['sector'], l[0], l[1], l[2], + coords['planet'], coords['satellite']) + self.protocol.player.planet = str(planet) def on_client_disconnect(self, player): if self.protocol.player is not None and self.protocol.player.logged_in: @@ -113,24 +136,92 @@ def on_client_disconnect(self, player): self.protocol.player.logged_in = False return True + @permissions(UserLevels.REGISTERED) + def nick(self, data): + """Changes your nickname.\nSyntax: /nick (new name)""" + if len(data) == 0: + self.protocol.send_chat_message(self.nick.__doc__) + return + name = " ".join(data) + org_name = self.protocol.player.org_name + for regex in self.regexes: # Replace problematic chars in client name + name = re.sub(regex, "", name) + if self.player_manager.get_by_name(name) or (self.player_manager.get_by_org_name(name) and org_name != name): + self.protocol.send_chat_message("There's already a player by that name.") + else: + old_name = self.protocol.player.colored_name(self.config.colors) + self.protocol.player.name = name + self.factory.broadcast("%s^green;'s name has been changed to %s" % ( + old_name, self.protocol.player.colored_name(self.config.colors))) + @permissions(UserLevels.ADMIN) - def delete_player(self, data): + def nick_set(self, data): + """Changes player nickname.\nSyntax: /nick_set (name) (new name)""" + if len(data) <= 1: + self.protocol.send_chat_message(self.nick_set.__doc__) + return + try: + first_name, rest = extract_name(data) + for regex in self.regexes: # Replace problematic chars in client name + first_name = re.sub(regex, "", first_name) + except ValueError: + self.protocol.send_chat_message("Name not recognized. If it has spaces, please surround it by quotes!") + return + if rest is None or len(rest) == 0: + self.protocol.send_chat_message(self.nick_set.__doc__) + else: + try: + second_name = extract_name(rest)[0] + for regex in self.regexes: # Replace problematic chars in client name + second_name = re.sub(regex, "", second_name) + except ValueError: + self.protocol.send_chat_message( + "New name not recognized. If it has spaces, please surround it by quotes!") + return + player = self.player_manager.get_by_name(str(first_name)) + player2 = self.player_manager.get_by_name(str(second_name)) + org_player = self.player_manager.get_by_org_name(str(first_name)) + org_player2 = self.player_manager.get_by_org_name(str(second_name)) + if player: + first_uuid = player.uuid + elif org_player: + first_uuid = org_player.uuid + if player2: + second_uuid = player2.uuid + elif org_player2: + second_uuid = org_player2.uuid + if player or org_player: + if (player2 or org_player2) and first_uuid != second_uuid: + self.protocol.send_chat_message("There's already a player by that name.") + else: + old_name = player.colored_name(self.config.colors) + player.name = second_name + self.factory.broadcast("%s^green;'s name has been changed to %s" % ( + old_name, player.colored_name(self.config.colors))) + + @permissions(UserLevels.ADMIN) + def player_delete(self, data): + """Delete a player from database.\nSyntax: /player_del (player)""" + if len(data) == 0: + self.protocol.send_chat_message(self.player_del.__doc__) + return name = " ".join(data) if self.player_manager.get_logged_in_by_name(name) is not None: self.protocol.send_chat_message( - _("That player is currently logged in. Refusing to delete logged in character.")) + "That player is currently logged in. Refusing to delete logged in character.") return False else: player = self.player_manager.get_by_name(name) if player is None: self.protocol.send_chat_message( - _("Couldn't find a player named %s. Please check the spelling and try again.") % name) + "Couldn't find a player named %s. Please check the spelling and try again." % name) return False self.player_manager.delete(player) - self.protocol.send_chat_message(_("Deleted player with name %s.") % name) + self.protocol.send_chat_message("Deleted player with name %s." % name) @permissions(UserLevels.ADMIN) - def list_players(self, data): + def player_list(self, data): + """List registered players on the server.\nSyntax: /player_list [search term]""" if len(data) == 0: self.format_player_response(self.player_manager.all()) else: @@ -140,10 +231,18 @@ def list_players(self, data): def format_player_response(self, players): if len(players) <= 25: self.protocol.send_chat_message( - _("Results: %s") % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players])) + #_("Results: %s") % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players])) + "Results:\n%s" % "\n".join( + ["^cyan;%s: ^yellow;%s ^green;: ^gray;%s" % ( + player.uuid, player.colored_name(self.config.colors), player.org_name) for player in + players])) else: self.protocol.send_chat_message( - _("Results: %s)" % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players[:25]]))) + #_("Results: %s)" % "\n".join(["%s: %s" % (player.uuid, player.name) for player in players[:25]]))) + "Results:\n%s" % "\n".join( + ["^cyan;%s: ^yellow;%s ^green;: ^gray;%s" % ( + player.uuid, player.colored_name(self.config.colors), player.org_name) for player in + players[:25]])) self.protocol.send_chat_message( - _("And %d more. Narrow it down with SQL like syntax. Feel free to use a *, it will be replaced appropriately.") % ( + "And %d more. Narrow it down with SQL like syntax. Feel free to use a *, it will be replaced appropriately." % ( len(players) - 25)) diff --git a/plugins/core/starbound_config_manager/starbound_config_manager.py b/plugins/core/starbound_config_manager/starbound_config_manager.py index bfb9027..9cfb4eb 100644 --- a/plugins/core/starbound_config_manager/starbound_config_manager.py +++ b/plugins/core/starbound_config_manager/starbound_config_manager.py @@ -34,6 +34,10 @@ def activate(self): @permissions(UserLevels.GUEST) def spawn(self, data): - __doc__ = _("""Moves your ship to spawn. Syntax: /spawn""") + """Warps your ship to spawn.\nSyntax: /spawn""" + on_ship = self.protocol.player.on_ship + if not on_ship: + self.protocol.send_chat_message("You need to be on a ship!") + return self.plugins['warpy_plugin'].move_player_ship(self.protocol, [x for x in self._spawn]) - self.protocol.send_chat_message(_("Moving your ship to spawn.")) \ No newline at end of file + self.protocol.send_chat_message("Moving your ship to spawn.") diff --git a/plugins/motd_plugin/motd_plugin.py b/plugins/motd_plugin/motd_plugin.py index aa7c372..eab6d91 100644 --- a/plugins/motd_plugin/motd_plugin.py +++ b/plugins/motd_plugin/motd_plugin.py @@ -9,7 +9,7 @@ class MOTDPlugin(SimpleCommandPlugin): successful connection. """ name = "motd_plugin" - commands = ["motd", "set_motd"] + commands = ["motd", "motd_set"] auto_activate = True def activate(self): @@ -25,19 +25,19 @@ def after_connect_response(self, data): self.send_motd() def send_motd(self): - self.protocol.send_chat_message(_("Message of the Day:\n%s") % self._motd) + #self.protocol.send_chat_message("^yellow;%s" % self._motd) + if not self.config.server_name: + self.config.server_name = "MY" + self.protocol.send_chat_message("%s" % (self._motd)) @permissions(UserLevels.GUEST) def motd(self, data): - __doc__ = _("""Displays the message of the day. Usage: /motd""") - if len(data) == 0: - self.send_motd() - else: - self.set_motd(data) + """Displays the message of the day.\nSyntax: /motd""" + self.send_motd() @permissions(UserLevels.MODERATOR) - def set_motd(self, motd): - __doc__ = _("""Sets the message of the day to a new value. Usage: /set_motd [New message of the day]""") + def motd_set(self, motd): + """Sets the message of the day to a new value.\nSyntax: /motd_set (new message of the day)""" try: self._motd = " ".join(motd).encode("utf-8") self.config.plugin_config['motd'] = self._motd diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index e057ef1..1d4548f 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -1,6 +1,8 @@ +import re from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import UserLevels, permissions from packets import entity_create, EntityType, star_string +from utility_functions import extract_name class PlanetProtectPlugin(SimpleCommandPlugin): @@ -10,7 +12,7 @@ class PlanetProtectPlugin(SimpleCommandPlugin): """ name = "planet_protect" description = "Protects planets." - commands = ["protect", "unprotect"] + commands = ["protect", "unprotect", "protect_list", "protect_all"] depends = ["player_manager", "command_dispatcher"] def activate(self): @@ -19,63 +21,160 @@ def activate(self): for n in ["on_" + n.lower() for n in bad_packets]: setattr(self, n, (lambda x: self.planet_check())) self.protected_planets = self.config.plugin_config.get("protected_planets", []) + self.player_planets = self.config.plugin_config.get("player_planets", {}) self.blacklist = self.config.plugin_config.get("blacklist", []) - self.player_manager = self.plugins.get("player_manager", []) + self.player_manager = self.plugins["player_manager"].player_manager self.protect_everything = self.config.plugin_config.get("protect_everything", []) + self.regexes = self.plugins['player_manager'].regexes self.block_all = False def planet_check(self): - if self.protect_everything or ( - not self.protocol.player.on_ship and self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.REGISTERED): + if self.protocol.player.on_ship: + return True + elif self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.ADMIN: + name = self.protocol.player.org_name + if name in self.player_planets[self.protocol.player.planet]: + return True + else: + return False + elif self.protect_everything and self.protocol.player.access_level < UserLevels.REGISTERED: return False else: return True - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def protect(self, data): - __doc__ = _("""Protects the current planet. Only registered users can build on protected planets. Syntax: /protect""") + """Protects the current planet. Only administrators and allowed players can build on protected planets.\nSyntax: /protect [player]""" planet = self.protocol.player.planet on_ship = self.protocol.player.on_ship - if on_ship and not ("force" in " ".join(data).lower()): - self.protocol.send_chat_message(_("Can't protect ships (at the moment)")) + if len(data) == 0: + addplayer = self.protocol.player.org_name + first_name_color = self.protocol.player.colored_name(self.config.colors) + else: + self.logger.info("stream: %s" % data) + addplayer = data[0] + try: + addplayer, rest = extract_name(data) + self.logger.info("name: %s" % str(addplayer)) + addplayer = self.player_manager.get_by_name(addplayer).org_name + first_name_color = self.player_manager.get_by_org_name(addplayer).colored_name(self.config.colors) + except: + self.protocol.send_chat_message("There's no player named: ^yellow;%s" % str(addplayer)) + return + + first_name = str(addplayer) + + try: + if first_name in self.player_planets[self.protocol.player.planet]: + self.protocol.send_chat_message( + "Player ^yellow;%s^green; is already in planet protect list." % first_name_color) + return + except: + pass + + planet = self.protocol.player.planet # reset planet back to current planet + if on_ship: + self.protocol.send_chat_message("Can't protect ships (at the moment)") return if planet not in self.protected_planets: self.protected_planets.append(planet) - self.protocol.send_chat_message(_("Planet successfully protected.")) + self.protocol.send_chat_message("Planet successfully protected.") self.logger.info("Protected planet %s", planet) + if len(first_name) > 0: + if planet not in self.player_planets: + self.player_planets[planet] = [first_name] + else: + self.player_planets[planet] = self.player_planets[planet] + [first_name] + self.protocol.send_chat_message("Adding ^yellow;%s^green; to planet list" % first_name_color) + else: + if len(first_name) == 0: + self.protocol.send_chat_message("Planet is already protected!") + else: + if planet not in self.player_planets: + self.player_planets[planet] = [first_name] + else: + self.player_planets[planet] = self.player_planets[planet] + [first_name] + self.protocol.send_chat_message("Adding ^yellow;%s^green; to planet list" % first_name_color) + self.save() + + @permissions(UserLevels.OWNER) + def protect_all(self, data): + """Toggles planetary protection (from guests).\nSyntax: /protect_all""" + if self.protect_everything: + self.protect_everything = False + self.factory.broadcast("Planetary protection is now ^yellow;DISABLED") else: - self.protocol.send_chat_message(_("Planet is already protected!")) + self.protect_everything = True + self.factory.broadcast("Planetary protection is now ^red;ENABLED") self.save() - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) + def protect_list(self, data): + """Displays players registered to the protected planet.\nSyntax: /protect_list""" + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + if on_ship: + self.protocol.send_chat_message("Can't protect ships (at the moment)") + return + if planet in self.player_planets: + self.protocol.send_chat_message("Players registered to this planet: ^yellow;" + '^green;, ^yellow;'.join( + self.player_planets[planet]).replace('[', '').replace(']', '')) # .replace("'", '') + else: + self.protocol.send_chat_message("Planet is not protected!") + + @permissions(UserLevels.MODERATOR) def unprotect(self, data): - __doc__ = _("""Removes the protection from the current planet. Syntax: /unprotect""") + """Removes the protection from the current planet, or removes a registered player.\nSyntax: /unprotect [player]""" planet = self.protocol.player.planet on_ship = self.protocol.player.on_ship - if on_ship and not ("force" in " ".join(data).lower()): - self.protocol.send_chat_message(_("Can't protect ships (at the moment)")) + if len(data) == 0: + addplayer = self.protocol.player.org_name + first_name_color = self.protocol.player.colored_name(self.config.colors) + else: + addplayer, rest = extract_name(data) + first_name_color = addplayer + first_name = str(addplayer) + if on_ship: + self.protocol.send_chat_message("Can't protect ships (at the moment)") return - if planet in self.protected_planets: - self.protected_planets.remove(planet) - self.protocol.send_chat_message(_("Planet successfully unprotected.")) - self.logger.info("Unprotected planet %s", planet) + if len(data) == 0: + if planet in self.protected_planets: + del self.player_planets[planet] + self.protected_planets.remove(planet) + self.protocol.send_chat_message("Planet successfully unprotected.") + self.logger.info("Unprotected planet %s", planet) + else: + self.protocol.send_chat_message("Planet is not protected!") else: - self.protocol.send_chat_message(_("Planet is not protected!")) + if first_name in self.player_planets[planet]: + self.player_planets[planet].remove(first_name) + self.protocol.send_chat_message("Removed ^yellow;" + first_name_color + "^green; from planet list") + else: + self.protocol.send_chat_message( + "Cannot remove ^yellow;" + first_name_color + "^green; from planet list (not in list)") self.save() def save(self): self.config.plugin_config['protected_planets'] = self.protected_planets + self.config.plugin_config['player_planets'] = self.player_planets self.config.plugin_config['blacklist'] = self.blacklist + self.config.plugin_config['protect_everything'] = self.protect_everything + self.config.save() #we want to save permissions just in case def on_entity_create(self, data): - if self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level <= UserLevels.MODERATOR: - entities = entity_create.parse(data.data) - for entity in entities.entity: - if entity.entity_type == EntityType.PROJECTILE: - if self.block_all: return False - p_type = star_string("").parse(entity.entity) - if p_type in self.blacklist: - self.logger.debug( - "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", - self.protocol.player.name, p_type) - return False + """Projectile protection check""" + if self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.ADMIN: + name = self.protocol.player.org_name + if name in self.player_planets[self.protocol.player.planet]: + return True + else: + entities = entity_create.parse(data.data) + for entity in entities.entity: + if entity.entity_type == EntityType.PROJECTILE: + if self.block_all: return False + p_type = star_string("").parse(entity.entity) + if p_type in self.blacklist: + self.logger.info( + "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", + self.protocol.player.org_name, p_type) + return False diff --git a/plugins/plugin_manager_plugin/plugin_manager_plugin.py b/plugins/plugin_manager_plugin/plugin_manager_plugin.py index 8d2ce1e..2cce4e8 100644 --- a/plugins/plugin_manager_plugin/plugin_manager_plugin.py +++ b/plugins/plugin_manager_plugin/plugin_manager_plugin.py @@ -4,9 +4,9 @@ class PluginManagerPlugin(SimpleCommandPlugin): - """ Provides a simple chat interface to the PluginManager""" + """Provides a simple chat interface to the PluginManager""" name = "plugin_manager" - commands = ["list_plugins", "enable_plugin", "disable_plugin", "help"] + commands = ["plugin_list", "plugin_enable", "plugin_disable", "help"] auto_activate = True @property @@ -14,64 +14,68 @@ def plugin_manager(self): return self.protocol.plugin_manager @permissions(UserLevels.ADMIN) - def list_plugins(self, data): - __doc__ = """Lists all currently loaded plugins. Syntax: /list_plugins""" - self.protocol.send_chat_message(_("Currently loaded plugins: %s") % " ".join( + def plugin_list(self, data): + """Displays all currently loaded plugins.\nSyntax: /plugin_list""" + self.protocol.send_chat_message("Currently loaded plugins: ^yellow;%s" % "^green;, ^yellow;".join( [plugin.name for plugin in self.plugin_manager.plugins.itervalues() if plugin.active])) inactive = [plugin.name for plugin in self.plugin_manager.plugins.itervalues() if not plugin.active] if len(inactive) > 0: - self.protocol.send_chat_message(_("Inactive plugins: %s") % " ".join( + self.protocol.send_chat_message("Inactive plugins: ^red;%s" % "^green;, ^red;".join( [plugin.name for plugin in self.plugin_manager.plugins.itervalues() if not plugin.active])) - @permissions(UserLevels.ADMIN) - def disable_plugin(self, data): - __doc__ = """Disables a currently activated plugin. Syntax: /disable_plugin [plugin name]""" + @permissions(UserLevels.OWNER) + def plugin_disable(self, data): + """Disables a currently activated plugin.\nSyntax: /plugin_disable (plugin name)""" self.logger.debug("disable_plugin called: %s" " ".join(data)) if len(data) == 0: - self.protocol.send_chat_message(_("You have to specify a plugin.")) + self.protocol.send_chat_message("You have to specify a plugin.") return try: plugin = self.plugin_manager.get_by_name(data[0]) except PluginNotFound: - self.protocol.send_chat_message(_("Couldn't find a plugin with the name %s") % data[0]) + self.protocol.send_chat_message("Couldn't find a plugin with the name %s" % data[0]) return if plugin is self: - self.protocol.send_chat_message(_("Sorry, this plugin can't be deactivated.")) + self.protocol.send_chat_message("Sorry, this plugin can't be deactivated.") return if not plugin.active: - self.protocol.send_chat_message(_("That plugin is already deactivated.")) + self.protocol.send_chat_message("That plugin is already deactivated.") return plugin.deactivate() - self.protocol.send_chat_message(_("Successfully deactivated plugin.")) + self.protocol.send_chat_message("Successfully deactivated plugin.") - @permissions(UserLevels.ADMIN) - def enable_plugin(self, data): - __doc__ = """Enables a currently deactivated plugin. Syntax: /enable_plugin [plugin name]""" + @permissions(UserLevels.OWNER) + def plugin_enable(self, data): + """Enables a currently deactivated plugin.\nSyntax: /plugin_enable (plugin name)""" self.logger.debug("enable_plugin called: %s", " ".join(data)) if len(data) == 0: - self.protocol.send_chat_message(_("You have to specify a plugin.")) + self.protocol.send_chat_message("You have to specify a plugin.") return try: plugin = self.plugin_manager.get_by_name(data[0]) except PluginNotFound: - self.protocol.send_chat_message(_("Couldn't find a plugin with the name %s") % data[0]) + self.protocol.send_chat_message("Couldn't find a plugin with the name %s" % data[0]) return if plugin.active: - self.protocol.send_chat_message(_("That plugin is already active.")) + self.protocol.send_chat_message("That plugin is already active.") return plugin.activate() - self.protocol.send_chat_message(_("Successfully activated plugin.")) + self.protocol.send_chat_message("Successfully activated plugin.") @permissions(UserLevels.GUEST) def help(self, data): - __doc__ = """Prints help messages for plugin commands. Syntax: /help [command]""" + """Prints help messages for server commands.\nSyntax: /help [command]""" if len(data) > 0: command = data[0].lower() func = self.plugins['command_dispatcher'].commands.get(command, None) if func is None: - self.protocol.send_chat_message(_("Couldn't find a command with the name %s") % command) - self.protocol.send_chat_message("%s%s: %s" % (self.config.command_prefix, command, func.__doc__)) + self.protocol.send_chat_message("Couldn't find a command with the name ^yellow;%s" % command) + elif func.level > self.protocol.player.access_level: + self.protocol.send_chat_message("You do not have access to this command.") + else: + #self.protocol.send_chat_message("%s%s: %s" % (self.config.command_prefix, command, func.__doc__)) + self.protocol.send_chat_message("%s" % func.__doc__) else: available = [] for name, f in self.plugins['command_dispatcher'].commands.iteritems(): @@ -79,5 +83,5 @@ def help(self, data): available.append(name) available.sort(key=str.lower) self.protocol.send_chat_message( - _("Available commands: %s\nAlso try /help command") % ", ".join(available)) - return True \ No newline at end of file + "Available commands: ^yellow;%s\n^green;Get more help on commands with ^yellow;/help [command]" % "^green;, ^yellow;".join(available)) + return True diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 049ac04..6f3b924 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -10,7 +10,7 @@ class Warpy(SimpleCommandPlugin): """ name = "warpy_plugin" depends = ['command_dispatcher', 'player_manager'] - commands = ["warp", "move_ship"] + commands = ["warp", "warp_ship"] auto_activate = True def activate(self): @@ -19,7 +19,7 @@ def activate(self): @permissions(UserLevels.ADMIN) def warp(self, name): - __doc__ = _("""Warps you to a player's ship, or a player to another player's ship. Syntax: /warp [player name] OR /warp [player 1] [player 2]""") + """Warps you to a player's ship (or player to player).\nSyntax: /warp [player] (to player)""" if len(name) == 0: self.protocol.send_chat_message(self.warp.__doc__) return @@ -39,19 +39,25 @@ def warp(self, name): self.warp_player_to_player(first_name, second_name) @permissions(UserLevels.ADMIN) - def move_ship(self, location): - __doc__ = _("""Move your ship to another player or specific coordinates. Syntax: /move_ship [player_name] OR /move_ship [from player] [to player]""") + def warp_ship(self, location): + """Warps a player ship to another players ship.\nSyntax: /warp_ship [player] (to player)""" + if len(location) == 0: + self.protocol.send_chat_message(self.warp_ship.__doc__) + return try: first_name, rest = extract_name(location) - if not rest: - self.move_own_ship_to_player(first_name) - else: - self.move_player_ship_to_other(first_name, extract_name(rest)[0]) except ValueError as e: self.protocol.send_chat_message(str(e)) - self.protocol.send_chat_message(self.move_ship.__doc__) - except AttributeError: - self.protocol.send_chat_message(_("Couldn't find one or both of the users you specified.")) + return + if rest is None or len(rest) == 0: + self.move_own_ship_to_player(first_name) + else: + try: + second_name = extract_name(rest)[0] + except ValueError as e: + self.protocol.send_chat_message(str(e)) + return + self.move_player_ship_to_other(first_name, second_name) def warp_self_to_player(self, name): self.logger.debug("Warp command called by %s to %s", self.protocol.player.name, name) @@ -69,25 +75,28 @@ def warp_player_to_player(self, from_string, to_string): if from_player is not to_player: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t="WARP_OTHER_SHIP", - player=to_player.name.encode('utf-8'))) - + player=to_player.org_name.encode('utf-8'))) else: warp_packet = build_packet(Packets.WARP_COMMAND, warp_command_write(t='WARP_UP')) from_protocol.client_protocol.transport.write(warp_packet) + if from_string != to_string: + self.protocol.send_chat_message("Warped ^yellow;%s^green; to ^yellow;%s^green;." % (from_string, to_string)) + else: + self.protocol.send_chat_message("Warped to ^yellow;%s^green;." % to_string) else: - self.protocol.send_chat_message(_("No player by the name %s found.") % to_string) + self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % to_string) self.protocol.send_chat_message(self.warp.__doc__) return else: - self.protocol.send_chat_message(_("No player by the name %s found.") % from_string) + self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % from_string) self.protocol.send_chat_message(self.warp.__doc__) def move_player_ship(self, protocol, location): if len(location) < 5: - self.logger.warning(_("Couldn't derive a warp location in move_player_ship. Coordinates given: %s"), + self.logger.warning("Couldn't derive a warp location in move_player_ship. Coordinates given: ^cyan;%s", ":".join(location)) - self.protocol.send_chat_message(_("Sorry, an error occurred.")) + self.protocol.send_chat_message("Sorry, an error occurred.") return if len(location) == 5: satellite = 0 @@ -103,22 +112,32 @@ def move_player_ship(self, protocol, location): def move_own_ship_to_player(self, player_name): t = self.player_manager.get_logged_in_by_name(player_name) if t is None: - raise ValueError + self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % player_name) + self.protocol.send_chat_message(self.warp.__doc__) + return if t.planet == u"": self.protocol.send_chat_message( - _("Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped down to a planet since logging in?") % t.name) + "Sorry, we don't have a tracked planet location for ^yellow;%s^green;. Perhaps they haven't warped down to a planet since logging in?" % t.name) return self.move_player_ship(self.protocol, t.planet.split(":")) + self.protocol.send_chat_message("Warp drive engaged. Warping to ^yellow;%s^green;." % player_name) def move_player_ship_to_other(self, from_player, to_player): f = self.player_manager.get_logged_in_by_name(from_player) t = self.player_manager.get_logged_in_by_name(to_player) - if f is None or t is None: - raise ValueError + if f is None: + self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % from_player) + self.protocol.send_chat_message(self.warp.__doc__) + return + if t is None: + self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % to_player) + self.protocol.send_chat_message(self.warp.__doc__) + return if t.planet == u"": self.protocol.send_chat_message( - _("Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped to a planet since logging in?") % to_player) + "Sorry, we don't have a tracked planet location for %s. Perhaps they haven't warped to a planet since logging in?" % to_player) return self.move_player_ship(self.factory.protocols[f.protocol], t.planet.split(":")) + self.protocol.send_chat_message("Warp drive engaged. Warping ^yellow;%s^green; to ^yellow;%s^green;." % (from_player, to_player)) diff --git a/server.py b/server.py index 28292e9..c90f22e 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,7 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet -VERSION = "1.2.3" +VERSION = "1.4.4" TRACE = False TRACE_LVL = 9 logging.addLevelName(9, "TRACE") @@ -30,18 +30,18 @@ def port_check(upstream_hostname, upstream_port): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(1) - result = sock.connect_ex((upstream_hostname, upstream_port)) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(1) + result = sock.connect_ex((upstream_hostname, upstream_port)) - if result != 0: - sock.close() - return False - else: - sock.shutdown(SHUT_RDWR) - sock.close() + if result != 0: + sock.close() + return False + else: + sock.shutdown(SHUT_RDWR) + sock.close() - return True + return True class StarryPyServerProtocol(Protocol): @@ -85,7 +85,7 @@ def __init__(self): packets.Packets.TILE_LIQUID_UPDATE: self.tile_liquid_update, packets.Packets.TILE_DAMAGE_UPDATE: self.tile_damage_update, packets.Packets.TILE_MODIFICATION_FAILURE: self.tile_modification_failure, - packets.Packets.GIVE_ITEM: self.give_item, + packets.Packets.GIVE_ITEM: self.item, packets.Packets.SWAP_IN_CONTAINER_RESULT: self.swap_in_container_result, packets.Packets.ENVIRONMENT_UPDATE: self.environment_update, packets.Packets.ENTITY_INTERACT_RESULT: self.entity_interact_result, @@ -232,7 +232,7 @@ def tile_modification_failure(self, data): return True @route - def give_item(self, data): + def item(self, data): return True @route @@ -449,16 +449,28 @@ def connectionLost(self, reason=connectionDone): :param reason: The reason for the disconnection. :return: None """ - logger.info("Losing connection from IP: %s", self.transport.getPeer().host) - if self.player is not None: - self.player.logged_in = False - self.client_disconnect("") - if self.client_protocol is not None: - self.client_protocol.disconnect() try: - self.factory.protocols.pop(self.id) + if self.client_protocol is not None: + x = build_packet(packets.Packets.CLIENT_DISCONNECT, + packets.client_disconnect().build(Container(data=0))) + if self.player is not None and self.player.logged_in: + self.client_disconnect(x) + self.client_protocol.transport.write(x) + self.client_protocol.transport.abortConnection() except: - self.logger.trace("Protocol was not in factory list. This should not happen.") + logger.error("Couldn't disconnect protocol.") + finally: + try: + self.factory.protocols.pop(self.id) + except: + logger.info("Protocol was not in factory list. This should not happen.") + logger.info("protocol id: %s" % self.id) + finally: + logger.info("Lost connection from IP: %s", self.transport.getPeer().host) + self.transport.abortConnection() + + def die(self): + self.connectionLost() class ClientProtocol(Protocol): @@ -602,16 +614,14 @@ def buildProtocol(self, address): def reap_dead_protocols(self): logger.debug("Reaping dead connections.") count = 0 - start_time = datetime.datetime.utcnow() + start_time = datetime.datetime.now() for protocol in self.protocols.itervalues(): - if ( - protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: + if (protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: logger.trace("Reaping protocol %s. Reason: Server protocol timeout.", protocol.id) protocol.connectionLost() count += 1 continue - if protocol.client_protocol is not None and ( - protocol.client_protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: + if protocol.client_protocol is not None and (protocol.client_protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: protocol.connectionLost() logger.trace("Reaping protocol %s. Reason: Client protocol timeout.", protocol.id) count += 1 @@ -639,16 +649,20 @@ def buildProtocol(self, address): protocol.server_protocol = self.server_protocol return protocol def init_localization(): - locale.setlocale(locale.LC_ALL, '') - loc = locale.getlocale() - filename = "res/messages_%s.mo" % locale.getlocale()[0][0:2] try: + locale.setlocale(locale.LC_ALL, '') + except: + locale.setlocale(locale.LC_ALL, 'en_US.utf8') + """try: + loc = locale.getlocale() + filename = "res/messages_%s.mo" % locale.getlocale()[0][0:2] print "Opening message file %s for locale %s." % (filename, loc[0]) - trans = gettext.GNUTranslations(open(filename, "rb" )) - except IOError: + trans = gettext.GNUTranslations(open(filename, "rb")) + except (IOError, TypeError, IndexError): print "Locale not found. Using default messages." trans = gettext.NullTranslations() - trans.install() + trans.install()""" + if __name__ == '__main__': init_localization() From b7c1be467ca8bfa3400625a0e238b136d3a4e9d2 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 4 Jan 2015 00:20:46 -0500 Subject: [PATCH 49/95] A few more fixes --- config/config.json.default | 21 ++++++++++++++++----- plugins/core/player_manager/manager.py | 1 - plugins/players/__init__.py | 1 + plugins/players/players.py | 21 +++++++++++++++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 plugins/players/__init__.py create mode 100644 plugins/players/players.py diff --git a/config/config.json.default b/config/config.json.default index abfcfc6..a61db7d 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -2,6 +2,7 @@ "bind_address": "", "bind_port": 21025, "chat_prefix": "@", + "chattimestamps": true, "colors": { "admin": "^#C443F7;", "default": "^#F7EB43;", @@ -51,7 +52,7 @@ 5 ] ], - "message": "Welcome to the server! Here are some starter items to get you off to a good start." + "message": "Welcome to the server!" }, "planet_protect": { "auto_activate": true, @@ -59,12 +60,21 @@ "bad_packets": [ "CONNECT_WIRE", "DISCONNECT_ALL_WIRES", - "OPEN_CONTAINER", - "CLOSE_CONTAINER", "SWAP_IN_CONTAINER", "DAMAGE_TILE", "DAMAGE_TILE_GROUP", - "REQUEST_DROP", + "MODIFY_TILE_LIST" + ], + "bad_packets_ship": [ + "ENTITY_INTERACT", + "OPEN_CONTAINER", + "CLOSE_CONTAINER" + ], + "bad_packets_mild": [ + "CONNECT_WIRE", + "DISCONNECT_ALL_WIRES", + "DAMAGE_TILE", + "DAMAGE_TILE_GROUP", "MODIFY_TILE_LIST" ], "blacklist": [ @@ -148,7 +158,7 @@ "auto_activate": true, "name_removal_regexes": [ "\\^#[\\w]+;", - "[\\w]+" + "[^ \\w]+" ] }, "plugin_manager": { @@ -168,6 +178,7 @@ "port_check": true, "reap_time": 10, "server_connect_timeout": 5, + "server_name": "--ADD NAME--", "starbound_path": "/opt/starbound/", "upstream_hostname": "localhost", "upstream_port": 21024 diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 7ed0b53..11127e7 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -6,7 +6,6 @@ import json import sqlite3 -from enum import Enum from sqlalchemy.ext.mutable import Mutable from sqlalchemy.orm import sessionmaker, relationship, backref from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKey, Boolean, func diff --git a/plugins/players/__init__.py b/plugins/players/__init__.py new file mode 100644 index 0000000..6c4baa9 --- /dev/null +++ b/plugins/players/__init__.py @@ -0,0 +1 @@ +from players import PlayersPlugin diff --git a/plugins/players/players.py b/plugins/players/players.py new file mode 100644 index 0000000..8e9f375 --- /dev/null +++ b/plugins/players/players.py @@ -0,0 +1,21 @@ +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels + + +class PlayersPlugin(SimpleCommandPlugin): + """ + Very simple plugin that adds /players command alias for /who command in StarryPy. + """ + name = "players_plugin" + depends = ["command_dispatcher", "user_management_commands"] + commands = ["players"] + auto_activate = True + + def activate(self): + super(PlayersPlugin, self).activate() + self.user_commands = self.plugins['user_management_commands'] + + @permissions(UserLevels.GUEST) + def players(self, data): + """Displays all current players on the server.\nSyntax: /players""" + self.user_commands.who(data) From fc1ff52ed55df1170e90284d45dda779f1203b39 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 4 Jan 2015 12:54:47 -0500 Subject: [PATCH 50/95] Initial work on bringing packets up to the newest versions. A lot of guesswork going on right now... --- packets/data_types.py | 4 +- packets/packet_types.py | 118 +++++++++++++++++++++++----------------- 2 files changed, 70 insertions(+), 52 deletions(-) diff --git a/packets/data_types.py b/packets/data_types.py index 676301d..37aed19 100644 --- a/packets/data_types.py +++ b/packets/data_types.py @@ -75,10 +75,10 @@ def _encode(self, obj, context): return obj def _decode(self, obj, context): return "".join(obj) + star_string_struct = lambda name="star_string": Struct(name, VLQ("length"), - String("string", lambda ctx: ctx.length) -) + String("string", lambda ctx: ctx.length)) class VariantVariant(Construct): def _parse(self, stream, context): diff --git a/packets/packet_types.py b/packets/packet_types.py index 92cb7f6..022fb9b 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -1,6 +1,6 @@ from construct import * from enum import IntEnum -from data_types import SignedVLQ, VLQ, Variant, star_string, DictVariant, StarByteArray +from data_types import SignedVLQ, VLQ, Variant, star_string, DictVariant, StarByteArray class Direction(IntEnum): @@ -10,54 +10,59 @@ class Direction(IntEnum): class Packets(IntEnum): PROTOCOL_VERSION = 0 - CONNECT_RESPONSE = 1 - SERVER_DISCONNECT = 2 + SERVER_DISCONNECT = 1 + CONNECT_RESPONSE = 2 HANDSHAKE_CHALLENGE = 3 CHAT_RECEIVED = 4 UNIVERSE_TIME_UPDATE = 5 - CELESTIALRESPONSE = 6 + CELESTIAL_RESPONSE = 6 CLIENT_CONNECT = 7 - CLIENT_DISCONNECT = 8 + CLIENT_DISCONNECT_REQUEST = 8 HANDSHAKE_RESPONSE = 9 - WARP_COMMAND = 10 - CHAT_SENT = 11 - CELESTIALREQUEST = 12 - CLIENT_CONTEXT_UPDATE = 13 - WORLD_START = 14 - WORLD_STOP = 15 - TILE_ARRAY_UPDATE = 16 - TILE_UPDATE = 17 - TILE_LIQUID_UPDATE = 18 - TILE_DAMAGE_UPDATE = 19 - TILE_MODIFICATION_FAILURE = 20 - GIVE_ITEM = 21 - SWAP_IN_CONTAINER_RESULT = 22 - ENVIRONMENT_UPDATE = 23 - ENTITY_INTERACT_RESULT = 24 - MODIFY_TILE_LIST = 25 - DAMAGE_TILE = 26 - DAMAGE_TILE_GROUP = 27 - REQUEST_DROP = 28 - SPAWN_ENTITY = 29 - ENTITY_INTERACT = 30 - CONNECT_WIRE = 31 - DISCONNECT_ALL_WIRES = 32 - OPEN_CONTAINER = 33 - CLOSE_CONTAINER = 34 - SWAP_IN_CONTAINER = 35 - ITEM_APPLY_IN_CONTAINER = 36 - START_CRAFTING_IN_CONTAINER = 37 - STOP_CRAFTING_IN_CONTAINER = 38 - BURN_CONTAINER = 39 - CLEAR_CONTAINER = 40 - WORLD_UPDATE = 41 - ENTITY_CREATE = 42 - ENTITY_UPDATE = 43 - ENTITY_DESTROY = 44 - DAMAGE_NOTIFICATION = 45 - STATUS_EFFECT_REQUEST = 46 - UPDATE_WORLD_PROPERTIES = 47 - HEARTBEAT = 48 + PLAYER_WARP = 10 + FLY_SHIP = 11 + CHAT_SENT = 12 + CELESTIAL_REQUEST = 13 + CLIENT_CONTEXT_UPDATE = 14 + WORLD_START = 15 + WORLD_STOP = 16 + CENTRAL_STRUCTURE_UPDATE = 17 + TILE_ARRAY_UPDATE = 18 + TILE_UPDATE = 19 + TILE_LIQUID_UPDATE = 20 + TILE_DAMAGE_UPDATE = 21 + TILE_MODIFICATION_FAILURE = 22 + GIVE_ITEM = 23 + SWAP_IN_CONTAINER_RESULT = 24 + ENVIRONMENT_UPDATE = 25 + ENTITY_INTERACT_RESULT = 26 + UPDATE_TILE_PROTECTION = 27 + MODIFY_TILE_LIST = 28 + DAMAGE_TILE_GROUP = 29 + COLLECT_LIQUID = 30 + REQUEST_DROP = 31 + SPAWN_ENTITY = 32 + ENTITY_INTERACT = 33 + CONNECT_WIRE = 34 + DISCONNECT_ALL_WIRES = 35 + OPEN_CONTAINER = 36 + CLOSE_CONTAINER = 37 + SWAP_IN_CONTAINER = 38 + ITEM_APPLY_IN_CONTAINER = 39 + START_CRAFTING_IN_CONTAINER = 40 + STOP_CRAFTING_IN_CONTAINER = 41 + BURN_CONTAINER = 42 + CLEAR_CONTAINER = 43 + WORLD_CLIENT_STATE_UPDATE = 44 + ENTITY_CREATE = 45 + ENTITY_UPDATE = 46 + ENTITY_DESTROY = 47 + HIT_REQUEST = 48 + DAMAGE_REQUEST = 49 + DAMAGE_NOTIFICATION = 50 + CALL_SCRIPTED_ENTITY = 51 + UPDATE_WORLD_PROPERTIES = 52 + HEARTBEAT = 53 class EntityType(IntEnum): @@ -70,6 +75,14 @@ class EntityType(IntEnum): PLANT = 5 PLANTDROP = 6 EFFECT = 7 + NPC = 8 + + +class MessageContextMode(IntEnum): + CHANNEL = 1 + BROADCAST = 2 + WHISPER = 3 + COMMAND_RESULT = 4 class PacketOutOfOrder(Exception): @@ -119,8 +132,12 @@ def _decode(self, obj, context): star_string("reject_reason")) chat_received = lambda name="chat_received": Struct(name, - Byte("chat_channel"), - star_string("world"), + Struct("message_context", + Byte("mode"), + If(lambda ctx: ctx.mode is True, + star_string("chat_channel") + ) + ), UBInt32("client_id"), star_string("name"), star_string("message")) @@ -180,12 +197,13 @@ def _decode(self, obj, context): world_start = lambda name="world_start": Struct(name, - Variant("planet"), - Variant("world_structure"), + Variant("planet"), # rename to templateData? + #Variant("world_structure"), StarByteArray("sky_structure"), StarByteArray("weather_data"), - BFloat32("spawn_x"), - BFloat32("spawn_y"), + #BFloat32("spawn_x"), + #BFloat32("spawn_y"), + Array(2, BFloat32("coordinate")), Variant("world_properties"), UBInt32("client_id"), Flag("local_interpolation")) From 735dbf2bffc17f5bc95ad84882a0f250d01385d1 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 4 Jan 2015 13:55:46 -0500 Subject: [PATCH 51/95] More packet editing. tried correcting things to match SB documentation. added own comment directives in per-packet to help keep track. --- packets/packet_types.py | 61 ++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/packets/packet_types.py b/packets/packet_types.py index 022fb9b..b126928 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -98,12 +98,15 @@ def _decode(self, obj, context): return obj.encode("hex") +# may need to be corrected. new version only has hash, uses ByteArray handshake_response = lambda name="handshake_response": Struct(name, star_string("claim_response"), star_string("hash")) +# small correction. added proper context. may need to check if this is correct (need double. used bfloat64). universe_time_update = lambda name="universe_time": Struct(name, - VLQ("unknown")) + #VLQ("unknown")) + BFloat64("universe_time")) packet = lambda name="base_packet": Struct(name, Byte("id"), @@ -115,22 +118,28 @@ def _decode(self, obj, context): Byte("id"), SignedVLQ("payload_size")) +# should still work. nothing's changed here. protocol_version = lambda name="protocol_version": Struct(name, UBInt32("server_build")) connection = lambda name="connection": Struct(name, GreedyRange(Byte("compressed_data"))) +# may need to be corrected. new version only has salt, uses ByteArray handshake_challenge = lambda name="handshake_challenge": Struct(name, star_string("claim_message"), star_string("salt"), SBInt32("round_count")) +# Needs attention connect_response = lambda name="connect_response": Struct(name, Flag("success"), VLQ("client_id"), - star_string("reject_reason")) + star_string("reject_reason") + # may need to add something here CelestialBaseInformation + ) +# corrected. needs testing chat_received = lambda name="chat_received": Struct(name, Struct("message_context", Byte("mode"), @@ -142,23 +151,35 @@ def _decode(self, obj, context): star_string("name"), star_string("message")) +# corrected. shouldn't need too much testing chat_sent = lambda name="chat_sent": Struct(name, star_string("message"), - Byte("chat_channel")) + Enum(Byte("send_mode"), + BROADCAST=1, + LOCAL=2, + PARTY=3) + ) +# quite a bit of guesswork and hackery here with the ship_upgrades. client_connect = lambda name="client_connect": Struct(name, VLQ("asset_digest_length"), String("asset_digest", lambda ctx: ctx.asset_digest_length), - Variant("claim"), + #Variant("claim"), # no longer used? Flag("uuid_exists"), If(lambda ctx: ctx.uuid_exists is True, HexAdapter(Field("uuid", 16)) ), star_string("name"), star_string("species"), - VLQ("shipworld_length"), - Field("shipworld", lambda ctx: ctx.shipworld_length), + #VLQ("shipworld_length"), + #Field("shipworld", lambda ctx: ctx.shipworld_length), + StarByteArray("ship_data"), + # Replace: ShipUpgrades + Struct("ship_upgrades", + UBInt32("ship_level"), + UBInt32("max_fuel"), + VLQ("capabilities")), star_string("account")) client_disconnect = lambda name="client_disconnect": Struct(name, @@ -196,6 +217,7 @@ def _decode(self, obj, context): player=player)) +# partially correct. Needs work on dungeon ID value world_start = lambda name="world_start": Struct(name, Variant("planet"), # rename to templateData? #Variant("world_structure"), @@ -211,6 +233,7 @@ def _decode(self, obj, context): world_stop = lambda name="world_stop": Struct(name, star_string("status")) +# I THINK this is ok. Will test later. give_item = lambda name="give_item": Struct(name, star_string("name"), VLQ("count"), @@ -222,12 +245,15 @@ def _decode(self, obj, context): variant_type=7, description='')) +# replaced with something closer matched to SB documentation update_world_properties = lambda name="world_properties": Struct(name, - UBInt8("count"), - Array(lambda ctx: ctx.count, - Struct("properties", - star_string("key"), - Variant("value")))) + DictVariant("updated_properties")) +#update_world_properties = lambda name="world_properties": Struct(name, +# UBInt8("count"), +# Array(lambda ctx: ctx.count, +# Struct("properties", +# star_string("key"), +# Variant("value")))) update_world_properties_write = lambda dictionary: update_world_properties().build( Container( @@ -242,11 +268,14 @@ def _decode(self, obj, context): String("entity", lambda ctx: ctx.entity_size), SignedVLQ("entity_id")))) +# replaced with something closer matched to SB documentation client_context_update = lambda name="client_context": Struct(name, - VLQ("length"), - Byte("arguments"), - Array(lambda ctx: ctx.arguments, - Struct("key", - Variant("value")))) + StarByteArray("update_data")) +#client_context_update = lambda name="client_context": Struct(name, +# VLQ("length"), +# Byte("arguments"), +# Array(lambda ctx: ctx.arguments, +# Struct("key", +# Variant("value")))) projectile = DictVariant("projectile") From 87545c934442660f6058bcfb057d6dae487da96c Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 4 Jan 2015 14:02:07 -0500 Subject: [PATCH 52/95] small changes to allow server to start for testing. will need to properly correct these latter. --- .../starbound_config_manager/starbound_config_manager.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/core/starbound_config_manager/starbound_config_manager.py b/plugins/core/starbound_config_manager/starbound_config_manager.py index 9cfb4eb..96f980d 100644 --- a/plugins/core/starbound_config_manager/starbound_config_manager.py +++ b/plugins/core/starbound_config_manager/starbound_config_manager.py @@ -13,7 +13,7 @@ class StarboundConfigManager(SimpleCommandPlugin): def activate(self): super(StarboundConfigManager, self).activate() try: - configuration_file = FilePath(self.config.starbound_path).child('starbound.config') + configuration_file = FilePath(self.config.starbound_path).child('starbound_server.config') if not configuration_file.exists(): raise FatalPluginError( "Could not open starbound configuration file. Tried path: %s" % configuration_file) @@ -30,7 +30,8 @@ def activate(self): raise FatalPluginError( "The starbound gamePort option (%d) does not match the config.json upstream_port (%d)." % ( starbound_config['gamePort'], self.config.upstream_port)) - self._spawn = starbound_config['defaultWorldCoordinate'].split(":") + #self._spawn = starbound_config['defaultWorldCoordinate'].split(":") + self._spawn = "junk" @permissions(UserLevels.GUEST) def spawn(self, data): From 7af5c397fd484bcead6129e8630dc6b9a061d23d Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 4 Jan 2015 14:13:59 -0500 Subject: [PATCH 53/95] corrected server.py to match new packet types --- server.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/server.py b/server.py index c90f22e..aa26382 100644 --- a/server.py +++ b/server.py @@ -65,23 +65,25 @@ def __init__(self): self.plugin_manager = None self.call_mapping = { packets.Packets.PROTOCOL_VERSION: self.protocol_version, - packets.Packets.CONNECT_RESPONSE: self.connect_response, packets.Packets.SERVER_DISCONNECT: self.server_disconnect, + packets.Packets.CONNECT_RESPONSE: self.connect_response, packets.Packets.HANDSHAKE_CHALLENGE: self.handshake_challenge, packets.Packets.CHAT_RECEIVED: self.chat_received, packets.Packets.UNIVERSE_TIME_UPDATE: self.universe_time_update, + packets.Packets.CELESTIAL_RESPONSE: lambda x: True, packets.Packets.CLIENT_CONNECT: self.client_connect, - packets.Packets.CLIENT_DISCONNECT: self.client_disconnect, + packets.Packets.CLIENT_DISCONNECT_REQUEST: self.client_disconnect, packets.Packets.HANDSHAKE_RESPONSE: self.handshake_response, - packets.Packets.WARP_COMMAND: self.warp_command, + packets.Packets.PLAYER_WARP: self.warp_command, + packets.Packets.FLY_SHIP: lambda x: True, packets.Packets.CHAT_SENT: self.chat_sent, + packets.Packets.CELESTIAL_REQUEST: lambda x: True, packets.Packets.CLIENT_CONTEXT_UPDATE: self.client_context_update, packets.Packets.WORLD_START: self.world_start, packets.Packets.WORLD_STOP: self.world_stop, + packets.Packets.CENTRAL_STRUCTURE_UPDATE: lambda x: True, packets.Packets.TILE_ARRAY_UPDATE: self.tile_array_update, packets.Packets.TILE_UPDATE: self.tile_update, - packets.Packets.CELESTIALRESPONSE: lambda x: True, - packets.Packets.CELESTIALREQUEST: lambda x: True, packets.Packets.TILE_LIQUID_UPDATE: self.tile_liquid_update, packets.Packets.TILE_DAMAGE_UPDATE: self.tile_damage_update, packets.Packets.TILE_MODIFICATION_FAILURE: self.tile_modification_failure, @@ -89,9 +91,10 @@ def __init__(self): packets.Packets.SWAP_IN_CONTAINER_RESULT: self.swap_in_container_result, packets.Packets.ENVIRONMENT_UPDATE: self.environment_update, packets.Packets.ENTITY_INTERACT_RESULT: self.entity_interact_result, + packets.Packets.UPDATE_TILE_PROTECTION: lambda x: True, packets.Packets.MODIFY_TILE_LIST: self.modify_tile_list, - packets.Packets.DAMAGE_TILE: self.damage_tile, packets.Packets.DAMAGE_TILE_GROUP: self.damage_tile_group, + packets.Packets.COLLECT_LIQUID: lambda x: True, packets.Packets.REQUEST_DROP: self.request_drop, packets.Packets.SPAWN_ENTITY: self.spawn_entity, packets.Packets.ENTITY_INTERACT: self.entity_interact, @@ -105,12 +108,13 @@ def __init__(self): packets.Packets.STOP_CRAFTING_IN_CONTAINER: self.stop_crafting_in_container, packets.Packets.BURN_CONTAINER: self.burn_container, packets.Packets.CLEAR_CONTAINER: self.clear_container, - packets.Packets.WORLD_UPDATE: self.world_update, + packets.Packets.WORLD_CLIENT_STATE_UPDATE: self.world_update, packets.Packets.ENTITY_CREATE: self.entity_create, packets.Packets.ENTITY_UPDATE: self.entity_update, packets.Packets.ENTITY_DESTROY: self.entity_destroy, + packets.Packets.DAMAGE_REQUEST: lambda x: True, packets.Packets.DAMAGE_NOTIFICATION: self.damage_notification, - packets.Packets.STATUS_EFFECT_REQUEST: self.status_effect_request, + packets.Packets.CALL_SCRIPTED_ENTITY: lambda x: True, packets.Packets.UPDATE_WORLD_PROPERTIES: self.update_world_properties, packets.Packets.HEARTBEAT: self.heartbeat, } From 71551216c4e05040b8f2561ff343128f7f0f693b Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Mon, 5 Jan 2015 11:28:01 -0500 Subject: [PATCH 54/95] Got everything working using a vanilla connection. Need to start whack-a-mole on plugin errors, namely warp. --- base_plugin.py | 6 + packets/packet_types.py | 76 ++-- plugins/announcer_plugin/announcer_plugin.py | 4 +- plugins/core/player_manager/plugin.py | 7 +- plugins/warpy_plugin/warpy_plugin.py | 7 +- res/messages.po | 417 ------------------- server.py | 38 +- utility_functions.py | 11 +- 8 files changed, 76 insertions(+), 490 deletions(-) delete mode 100644 res/messages.po diff --git a/base_plugin.py b/base_plugin.py index 2ca7153..cfc6b29 100644 --- a/base_plugin.py +++ b/base_plugin.py @@ -56,6 +56,9 @@ def on_handshake_challenge(self, data): def on_chat_received(self, data): return True + def on_celestial_request(self, data): + return True + def on_universe_time_update(self, data): return True @@ -197,6 +200,9 @@ def after_handshake_challenge(self, data): def after_chat_received(self, data): return True + def after_celestial_request(self, data): + return True + def after_universe_time_update(self, data): return True diff --git a/packets/packet_types.py b/packets/packet_types.py index b126928..e25d964 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -79,10 +79,10 @@ class EntityType(IntEnum): class MessageContextMode(IntEnum): - CHANNEL = 1 - BROADCAST = 2 - WHISPER = 3 - COMMAND_RESULT = 4 + CHANNEL = 0 + BROADCAST = 1 + WHISPER = 2 + COMMAND_RESULT = 3 class PacketOutOfOrder(Exception): @@ -141,12 +141,8 @@ def _decode(self, obj, context): # corrected. needs testing chat_received = lambda name="chat_received": Struct(name, - Struct("message_context", - Byte("mode"), - If(lambda ctx: ctx.mode is True, - star_string("chat_channel") - ) - ), + Byte("mode"), + star_string("chat_channel"), UBInt32("client_id"), star_string("name"), star_string("message")) @@ -155,9 +151,9 @@ def _decode(self, obj, context): chat_sent = lambda name="chat_sent": Struct(name, star_string("message"), Enum(Byte("send_mode"), - BROADCAST=1, - LOCAL=2, - PARTY=3) + BROADCAST=0, + LOCAL=1, + PARTY=2) ) # quite a bit of guesswork and hackery here with the ship_upgrades. @@ -165,28 +161,28 @@ def _decode(self, obj, context): VLQ("asset_digest_length"), String("asset_digest", lambda ctx: ctx.asset_digest_length), - #Variant("claim"), # no longer used? Flag("uuid_exists"), If(lambda ctx: ctx.uuid_exists is True, HexAdapter(Field("uuid", 16)) ), star_string("name"), star_string("species"), - #VLQ("shipworld_length"), - #Field("shipworld", lambda ctx: ctx.shipworld_length), StarByteArray("ship_data"), - # Replace: ShipUpgrades - Struct("ship_upgrades", - UBInt32("ship_level"), - UBInt32("max_fuel"), - VLQ("capabilities")), + UBInt32("ship_level"), + UBInt32("max_fuel"), + VLQ("capabilities"), star_string("account")) +server_disconnect = lambda name="server_disconnect": Struct(name, + star_string("reason")) + client_disconnect = lambda name="client_disconnect": Struct(name, Byte("data")) +celestial_request = lambda name="celestial_request": Struct(name, + GreedyRange(star_string("requests"))) + world_coordinate = lambda name="world_coordinate": Struct(name, - star_string("sector"), SBInt32("x"), SBInt32("y"), SBInt32("z"), @@ -203,11 +199,10 @@ def _decode(self, obj, context): world_coordinate(), star_string("player")) -warp_command_write = lambda t, sector=u'', x=0, y=0, z=0, planet=0, satellite=0, player=u'': warp_command().build( +warp_command_write = lambda t, x=0, y=0, z=0, planet=0, satellite=0, player=u'': warp_command().build( Container( warp_type=t, world_coordinate=Container( - sector=sector, x=x, y=y, z=z, @@ -220,11 +215,9 @@ def _decode(self, obj, context): # partially correct. Needs work on dungeon ID value world_start = lambda name="world_start": Struct(name, Variant("planet"), # rename to templateData? - #Variant("world_structure"), - StarByteArray("sky_structure"), + StarByteArray("sky_data"), StarByteArray("weather_data"), - #BFloat32("spawn_x"), - #BFloat32("spawn_y"), + #dungeon id stuff here Array(2, BFloat32("coordinate")), Variant("world_properties"), UBInt32("client_id"), @@ -246,14 +239,14 @@ def _decode(self, obj, context): description='')) # replaced with something closer matched to SB documentation -update_world_properties = lambda name="world_properties": Struct(name, - DictVariant("updated_properties")) #update_world_properties = lambda name="world_properties": Struct(name, -# UBInt8("count"), -# Array(lambda ctx: ctx.count, -# Struct("properties", -# star_string("key"), -# Variant("value")))) +# DictVariant("updated_properties")) +update_world_properties = lambda name="world_properties": Struct(name, + UBInt8("count"), + Array(lambda ctx: ctx.count, + Struct("properties", + star_string("key"), + Variant("value")))) update_world_properties_write = lambda dictionary: update_world_properties().build( Container( @@ -268,14 +261,11 @@ def _decode(self, obj, context): String("entity", lambda ctx: ctx.entity_size), SignedVLQ("entity_id")))) -# replaced with something closer matched to SB documentation client_context_update = lambda name="client_context": Struct(name, - StarByteArray("update_data")) -#client_context_update = lambda name="client_context": Struct(name, -# VLQ("length"), -# Byte("arguments"), -# Array(lambda ctx: ctx.arguments, -# Struct("key", -# Variant("value")))) + VLQ("length"), + Byte("arguments"), + Array(lambda ctx: ctx.arguments, + Struct("key", + Variant("value")))) projectile = DictVariant("projectile") diff --git a/plugins/announcer_plugin/announcer_plugin.py b/plugins/announcer_plugin/announcer_plugin.py index 2dd2927..d731daa 100644 --- a/plugins/announcer_plugin/announcer_plugin.py +++ b/plugins/announcer_plugin/announcer_plugin.py @@ -17,7 +17,7 @@ def after_connect_response(self, data): c = connect_response().parse(data.data) if c.success: self.factory.broadcast( - self.protocol.player.colored_name(self.config.colors) + " logged in.", 0, "", "Announcer") + self.protocol.player.colored_name(self.config.colors) + " logged in.", 0, "Announcer") except AttributeError: self.logger.debug("Attribute error in after_connect_response.") return @@ -28,5 +28,5 @@ def after_connect_response(self, data): def on_client_disconnect(self, data): if self.protocol.player is not None: self.factory.broadcast(self.protocol.player.colored_name(self.config.colors) + " logged out.", 0, - "", "Announcer") + "Announcer") diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 7122c9b..7392866 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -116,17 +116,16 @@ def on_connect_response(self, data): def after_world_start(self, data): world_start = packets.world_start().parse(data.data) - if 'fuel.max' in world_start['world_properties']: + if 'ship.maxFuel' in world_start['world_properties']: self.logger.info("Player %s is now on a ship.", self.protocol.player.name) self.protocol.player.on_ship = True self.protocol.player.planet = "On ship" else: coords = world_start.planet['celestialParameters']['coordinate'] parent_system = coords - location = parent_system['location'] - l = location + l = parent_system['location'] self.protocol.player.on_ship = False - planet = Planet(parent_system['sector'], l[0], l[1], l[2], + planet = Planet(l[0], l[1], l[2], coords['planet'], coords['satellite']) self.protocol.player.planet = str(planet) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 6f3b924..6b7cb71 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -73,11 +73,11 @@ def warp_player_to_player(self, from_string, to_string): if to_player is not None: from_protocol = self.factory.protocols[from_player.protocol] if from_player is not to_player: - warp_packet = build_packet(Packets.WARP_COMMAND, + warp_packet = build_packet(Packets.PLAYER_WARP, warp_command_write(t="WARP_OTHER_SHIP", player=to_player.org_name.encode('utf-8'))) else: - warp_packet = build_packet(Packets.WARP_COMMAND, + warp_packet = build_packet(Packets.PLAYER_WARP, warp_command_write(t='WARP_UP')) from_protocol.client_protocol.transport.write(warp_packet) if from_string != to_string: @@ -106,8 +106,7 @@ def move_player_ship(self, protocol, location): z = int(location.pop()) y = int(location.pop()) x = int(location.pop()) - sector = location.pop() - move_ship_to_coords(protocol, sector, x, y, z, planet, satellite) + move_ship_to_coords(protocol, x, y, z, planet, satellite) def move_own_ship_to_player(self, player_name): t = self.player_manager.get_logged_in_by_name(player_name) diff --git a/res/messages.po b/res/messages.po deleted file mode 100644 index 4a9792f..0000000 --- a/res/messages.po +++ /dev/null @@ -1,417 +0,0 @@ -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-02-18 23:27-0600\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: plugins/planet_protect/planet_protect_plugin.py:35 -msgid "" -"Protects the current planet. Only registered users can build on protected " -"planets. Syntax: /protect" -msgstr "" - -#: plugins/planet_protect/planet_protect_plugin.py:39 -#: plugins/planet_protect/planet_protect_plugin.py:55 -msgid "Can't protect ships (at the moment)" -msgstr "" - -#: plugins/planet_protect/planet_protect_plugin.py:43 -msgid "Planet successfully protected." -msgstr "" - -#: plugins/planet_protect/planet_protect_plugin.py:46 -msgid "Planet is already protected!" -msgstr "" - -#: plugins/planet_protect/planet_protect_plugin.py:51 -msgid "Removes the protection from the current planet. Syntax: /unprotect" -msgstr "" - -#: plugins/planet_protect/planet_protect_plugin.py:59 -msgid "Planet successfully unprotected." -msgstr "" - -#: plugins/planet_protect/planet_protect_plugin.py:62 -msgid "Planet is not protected!" -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:22 -msgid "" -"Warps you to a player's ship, or a player to another player's ship. Syntax: /" -"warp [player name] OR /warp [player 1] [player 2]" -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:43 -msgid "" -"Move your ship to another player or specific coordinates. Syntax: /move_ship " -"[player_name] OR /move_ship [from player] [to player]" -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:54 -msgid "Couldn't find one or both of the users you specified." -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:78 -#: plugins/warpy_plugin/warpy_plugin.py:82 -#, python-format -msgid "No player by the name %s found." -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:87 -#, python-format -msgid "" -"Couldn't derive a warp location in move_player_ship. Coordinates given: %s" -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:89 -msgid "Sorry, an error occurred." -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:108 -#, python-format -msgid "" -"Sorry, we don't have a tracked planet location for %s. Perhaps they haven't " -"warped down to a planet since logging in?" -msgstr "" - -#: plugins/warpy_plugin/warpy_plugin.py:120 -#, python-format -msgid "" -"Sorry, we don't have a tracked planet location for %s. Perhaps they haven't " -"warped to a planet since logging in?" -msgstr "" - -#: plugins/admin_messenger/admin_messenger.py:30 -#, python-format -msgid "Received an admin message from %s: %s." -msgstr "" - -#: plugins/admin_messenger/admin_messenger.py:38 -#, python-format -msgid "%sSERVER BROADCAST: %s%s" -msgstr "" - -#: plugins/motd_plugin/motd_plugin.py:28 -#, python-format -msgid "" -"Message of the Day:\n" -"%s" -msgstr "" - -#: plugins/motd_plugin/motd_plugin.py:32 -msgid "Displays the message of the day. Usage: /motd" -msgstr "" - -#: plugins/motd_plugin/motd_plugin.py:40 -msgid "" -"Sets the message of the day to a new value. Usage: /set_motd [New message of " -"the day]" -msgstr "" - -#: plugins/core/starbound_config_manager/starbound_config_manager.py:37 -msgid "Moves your ship to spawn. Syntax: /spawn" -msgstr "" - -#: plugins/core/starbound_config_manager/starbound_config_manager.py:39 -msgid "Moving your ship to spawn." -msgstr "" - -#: plugins/core/player_manager/plugin.py:122 -msgid "" -"That player is currently logged in. Refusing to delete logged in character." -msgstr "" - -#: plugins/core/player_manager/plugin.py:128 -#, python-format -msgid "" -"Couldn't find a player named %s. Please check the spelling and try again." -msgstr "" - -#: plugins/core/player_manager/plugin.py:131 -#, python-format -msgid "Deleted player with name %s." -msgstr "" - -#: plugins/core/player_manager/plugin.py:144 -#, python-format -msgid "Results: %s" -msgstr "" - -#: plugins/core/player_manager/plugin.py:147 -#, python-format -msgid "Results: %s)" -msgstr "" - -#: plugins/core/player_manager/plugin.py:149 -#, python-format -msgid "" -"And %d more. Narrow it down with SQL like syntax. Feel free to use a *, it " -"will be replaced appropriately." -msgstr "" - -#: plugins/core/player_manager/manager.py:365 -msgid "You are not an admin." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:26 -msgid "Returns all current users on the server. Syntax: /who" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:33 -msgid "Displays who is on your current planet." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:36 -#, python-format -msgid "%d players on your current planet: %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:40 -msgid "" -"Returns client data about the specified user. Syntax: /whois [user name]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:45 -#, python-format -msgid "" -"Name: %s\n" -"Userlevel: %s\n" -"UUID: %s\n" -"IP address: %s\n" -"Current planet: %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:49 -msgid "Player not found!" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:54 -msgid "" -"Promotes/demotes a user to a specific rank. Syntax: /promote [username] " -"[rank] (where rank is either: registered, moderator, admin, or guest))" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:72 -msgid "" -"You cannot change that user's access level as they are at least at an equal " -"level as you." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:84 -msgid "No such rank!\n" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:88 -#, python-format -msgid "%s: %s -> %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:94 -#, python-format -msgid "%s has promoted you to %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:100 -msgid "Player not found!\n" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:128 -msgid "Kicks a user from the server. Usage: /kick [username] [reason]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:145 -#, python-format -msgid "Couldn't find a user by the name %s." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:152 -msgid "Bans an IP (retrieved by /whois). Syntax: /ban [ip address]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:158 -#, python-format -msgid "Banned IP: %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:171 -msgid "Lists the currently banned IPs. Syntax: /bans" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:173 -#, python-format -msgid "IP: %s " -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:177 -msgid "Unbans an IP. Syntax: /unban [ip address]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:182 -#, python-format -msgid "Unbanned IP: %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:185 -#, python-format -msgid "Couldn't find IP: %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:190 -msgid "" -"Gives an item to a player. Syntax: /give [target player] [item name] " -"[optional: item count]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:195 -#, python-format -msgid "Please check your syntax. %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:199 -msgid "" -"Please check that the username you are referencing exists. If it has spaces, " -"please surround it by quotes." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:202 -#, python-format -msgid "An unknown error occured. %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:214 -#, python-format -msgid "%s has given you: %s (count: %s)" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:216 -msgid "Sent the item(s)." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:220 -msgid "You have to give an item name." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:222 -#, python-format -msgid "Couldn't find name: %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:229 -msgid "Mute a player. Syntax: /mute [player name]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:237 -msgid "You have been muted." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:238 -#, python-format -msgid "%s has been muted." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:242 -msgid "Unmute a currently muted player. Syntax: /unmute [player name]" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:246 -#, python-format -msgid "Couldn't find a user by the name %s" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:250 -msgid "You have been unmuted." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:251 -#, python-format -msgid "%s has been unmuted." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:255 -msgid "" -"Sets the server to passthrough mode. *This is irreversible without restart.* " -"Syntax: /passthrough" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:260 -msgid "" -"Shutdown the server in n seconds. Syntax: /shutdown [number of seconds] (>0)" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:264 -#, python-format -msgid "%s is not a number. Please enter a value in seconds." -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:266 -#, python-format -msgid "SERVER ANNOUNCEMENT: Server is shutting down in %s seconds!" -msgstr "" - -#: plugins/core/admin_commands_plugin/admin_command_plugin.py:278 -#, python-format -msgid "" -"You are currently muted and cannot speak. You are limited to commands and " -"admin chat (prefix your lines with %s for admin chat." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:19 -#, python-format -msgid "Currently loaded plugins: %s" -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:23 -#, python-format -msgid "Inactive plugins: %s" -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:31 -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:53 -msgid "You have to specify a plugin." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:36 -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:58 -#, python-format -msgid "Couldn't find a plugin with the name %s" -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:39 -msgid "Sorry, this plugin can't be deactivated." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:42 -msgid "That plugin is already deactivated." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:46 -msgid "Successfully deactivated plugin." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:61 -msgid "That plugin is already active." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:64 -msgid "Successfully activated plugin." -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:73 -#, python-format -msgid "Couldn't find a command with the name %s" -msgstr "" - -#: plugins/plugin_manager_plugin/plugin_manager_plugin.py:82 -#, python-format -msgid "" -"Available commands: %s\n" -"Also try /help command" -msgstr "" diff --git a/server.py b/server.py index aa26382..b89a9f9 100644 --- a/server.py +++ b/server.py @@ -77,7 +77,7 @@ def __init__(self): packets.Packets.PLAYER_WARP: self.warp_command, packets.Packets.FLY_SHIP: lambda x: True, packets.Packets.CHAT_SENT: self.chat_sent, - packets.Packets.CELESTIAL_REQUEST: lambda x: True, + packets.Packets.CELESTIAL_REQUEST: self.celestial_request, packets.Packets.CLIENT_CONTEXT_UPDATE: self.client_context_update, packets.Packets.WORLD_START: self.world_start, packets.Packets.WORLD_STOP: self.world_stop, @@ -146,7 +146,9 @@ def string_received(self, packet): Processing of parsed data is handled in handle_starbound_packets() :rtype : None """ - if 48 >= packet.id: + if 53 >= packet.id: + # DEBUG - print all packet IDs going to client + #logger.info("%s", packet.id) if self.handle_starbound_packets(packet): self.client_protocol.transport.write( packet.original_data) @@ -365,6 +367,16 @@ def chat_sent(self, data): """ return True + @route + def celestial_request(self, data): + """ + Called when the client requests celestial data...? + + :param data: Parsed chat packet. + :rtype : bool + """ + return True + @route def damage_notification(self, data): return True @@ -402,11 +414,11 @@ def warp_command(self, data): def handle_starbound_packets(self, p): """ This function is the meat of it all. Every time a full packet with - a derived ID <= 48, it is passed through here. + a derived ID <= 53, it is passed through here. """ return self.call_mapping[p.id](p) - def send_chat_message(self, text, channel=0, world='', name=''): + def send_chat_message(self, text, mode=0, channel='', name=''): """ Convenience function to send chat messages to the client. Note that this does *not* send messages to the server at large; broadcast should be @@ -414,8 +426,7 @@ def send_chat_message(self, text, channel=0, world='', name=''): otherwise. :param text: Message text, may contain multiple lines. - :param channel: The chat channel/context. 0 is global, 1 is planet. - :param world: World + :param channel: The chat channel/context. :param name: The name to display before the message. Blank leaves no brackets, otherwise it will be displayed as ``. :return: None @@ -426,9 +437,9 @@ def send_chat_message(self, text, channel=0, world='', name=''): self.send_chat_message(line) return if self.player is not None: - logger.trace("Calling send_chat_message from player %s on channel %d on world '%s' with reported username of %s with message: %s", self.player.name, channel, world, name, text) - chat_data = packets.chat_received().build(Container(chat_channel=channel, - world=world, + logger.trace("Calling send_chat_message from player %s on channel %d with mode %d with reported username of %s with message: %s", self.player.name, channel, mode, name, text) + chat_data = packets.chat_received().build(Container(mode=mode, + chat_channel=channel, client_id=0, name=name, message=text.encode("utf-8"))) @@ -455,7 +466,7 @@ def connectionLost(self, reason=connectionDone): """ try: if self.client_protocol is not None: - x = build_packet(packets.Packets.CLIENT_DISCONNECT, + x = build_packet(packets.Packets.CLIENT_DISCONNECT_REQUEST, packets.client_disconnect().build(Container(data=0))) if self.player is not None and self.player.logged_in: self.client_disconnect(x) @@ -535,7 +546,7 @@ def dataReceived(self, data): self.packet_stream += data def disconnect(self): - x = build_packet(packets.Packets.CLIENT_DISCONNECT, packets.client_disconnect().build(Container(data=0))) + x = build_packet(packets.Packets.CLIENT_DISCONNECT_REQUEST, packets.client_disconnect().build(Container(data=0))) self.transport.write(x) self.transport.abortConnection() @@ -571,14 +582,13 @@ def stopFactory(self): self.config.save() self.plugin_manager.die() - def broadcast(self, text, channel=1, world='', name=''): + def broadcast(self, text, mode=1, name=''): """ Convenience method to send a broadcasted message to all clients on the server. :param text: Message text - :param channel: Channel to broadcast on. 0 is global, 1 is planet. - :param world: World + :param mode: Channel to broadcast on. 0 is global, 1 is planet. :param name: The name to prepend before the message, format is :return: None """ diff --git a/utility_functions.py b/utility_functions.py index a28da38..86d11a9 100644 --- a/utility_functions.py +++ b/utility_functions.py @@ -49,8 +49,7 @@ def build_packet(packet_type, data): class Planet(object): - def __init__(self, sector, x, y, z, planet, satellite): - self.sector = sector + def __init__(self, x, y, z, planet, satellite): self.x = x self.y = y self.z = z @@ -58,15 +57,15 @@ def __init__(self, sector, x, y, z, planet, satellite): self.satellite = satellite def __str__(self): - return "%s:%d:%d:%d:%d:%d" % (self.sector, self.x, self.y, self.z, self.planet, self.satellite) + return "%d:%d:%d:%d:%d" % (self.x, self.y, self.z, self.planet, self.satellite) -def move_ship_to_coords(protocol, sector, x, y, z, planet, satellite): +def move_ship_to_coords(protocol, x, y, z, planet, satellite): logger.info("Moving %s's ship to coordinates: %s", protocol.player.name, - ":".join((sector, str(x), str(y), str(z), str(planet), str(satellite)))) + ":".join((str(x), str(y), str(z), str(planet), str(satellite)))) x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) warp_packet = build_packet(packets.Packets.WARP_COMMAND, - packets.warp_command_write(t="MOVE_SHIP", sector=sector, x=x, y=y, z=z, + packets.warp_command_write(t="MOVE_SHIP", x=x, y=y, z=z, planet=planet, satellite=satellite, player="".encode('utf-8'))) protocol.client_protocol.transport.write(warp_packet) From 08157b32e7c4bc65f1e37be74840f0f897c08d36 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Thu, 8 Jan 2015 02:39:32 -0500 Subject: [PATCH 55/95] Fixed warping. Added command for warping to outposts directly. --- .gitignore | 5 ++- packets/data_types.py | 29 ++++++++++++++++- packets/packet_types.py | 33 +++++++------------ plugins/core/player_manager/plugin.py | 5 +++ plugins/warpy_plugin/warpy_plugin.py | 46 ++++++++++++++++++++++++--- server.py | 4 ++- utility_functions.py | 2 +- 7 files changed, 94 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index d4e4c2f..37d2614 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,7 @@ nosetests.xml *.db *.db-journal *.log -.idea/ \ No newline at end of file +.idea/ + +# Vim mess cleanup +*.swp diff --git a/packets/data_types.py b/packets/data_types.py index 37aed19..6570456 100644 --- a/packets/data_types.py +++ b/packets/data_types.py @@ -1,6 +1,6 @@ import logging from construct import Construct, Struct, Byte, BFloat64, Flag, \ - String, Container + String, Container, Field from construct.core import _read_stream, _write_stream, Adapter @@ -95,6 +95,33 @@ def _parse(self, stream, context): c[key] = value return c +class WarpVariant(Construct): +# Not all variants have been properly treated! + def _parse(self, stream, context): + x = Byte("").parse_stream(stream) + if x == 0: + return None + elif x == 1: + return star_string().parse_stream(stream) + elif x == 2: + return None + elif x == 3: + flag = Flag("").parse_stream(stream) + return Field("", 16).parse_stream(stream).encode("hex") + def _build(self, obj, stream, context): + if len(obj) == 32: + _write_stream(stream, 1, chr(3)) + _write_stream(stream, 1, chr(1)) + _write_stream(stream, len(obj.decode("hex")), obj.decode("hex")) + return + elif obj is "outpost": + _write_stream(stream, 1, chr(1)) + star_string()._build(obj, stream, context) + return + elif obj is None: + _write_stream(stream, 1, chr(4)) + _write_stream(stream, 1, chr(0)) + return class Variant(Construct): def _parse(self, stream, context): diff --git a/packets/packet_types.py b/packets/packet_types.py index e25d964..67145cd 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -1,6 +1,7 @@ from construct import * from enum import IntEnum from data_types import SignedVLQ, VLQ, Variant, star_string, DictVariant, StarByteArray +from data_types import WarpVariant class Direction(IntEnum): @@ -118,7 +119,6 @@ def _decode(self, obj, context): Byte("id"), SignedVLQ("payload_size")) -# should still work. nothing's changed here. protocol_version = lambda name="protocol_version": Struct(name, UBInt32("server_build")) @@ -190,26 +190,18 @@ def _decode(self, obj, context): SBInt32("satellite")) warp_command = lambda name="warp_command": Struct(name, - Enum(UBInt32("warp_type"), - MOVE_SHIP=1, - WARP_UP=2, - WARP_OTHER_SHIP=3, - WARP_DOWN=4, - WARP_HOME=5), - world_coordinate(), - star_string("player")) - -warp_command_write = lambda t, x=0, y=0, z=0, planet=0, satellite=0, player=u'': warp_command().build( + Enum(UBInt8("warp_type"), + WARP_TO=0, + WARP_RETURN=1, + WARP_TO_HOME_WORLD=2, + WARP_TO_ORBITED_WORLD=3, + WARP_TO_OWN_SHIP=4), + WarpVariant("world_id")) + +warp_command_write = lambda t, world_id: warp_command().build( Container( warp_type=t, - world_coordinate=Container( - x=x, - y=y, - z=z, - planet=planet, - satellite=satellite - ), - player=player)) + world_id=world_id)) # partially correct. Needs work on dungeon ID value @@ -238,9 +230,6 @@ def _decode(self, obj, context): variant_type=7, description='')) -# replaced with something closer matched to SB documentation -#update_world_properties = lambda name="world_properties": Struct(name, -# DictVariant("updated_properties")) update_world_properties = lambda name="world_properties": Struct(name, UBInt8("count"), Array(lambda ctx: ctx.count, diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 7392866..369ea69 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -115,11 +115,16 @@ def on_connect_response(self, data): return True def after_world_start(self, data): + # may need to add more world types in here world_start = packets.world_start().parse(data.data) + # self.logger.debug("World start: %s", world_start) # debug world packets if 'ship.maxFuel' in world_start['world_properties']: self.logger.info("Player %s is now on a ship.", self.protocol.player.name) self.protocol.player.on_ship = True self.protocol.player.planet = "On ship" + elif world_start.planet['celestialParameters'] is None: + self.protocol.player.on_ship = False + self.protocol.player.planet = "On Outpost" else: coords = world_start.planet['celestialParameters']['coordinate'] parent_system = coords diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 6b7cb71..d2db7f5 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -1,3 +1,4 @@ +# -*- coding: UTF-8 -*- from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels from packets import warp_command_write, Packets, warp_command @@ -10,13 +11,19 @@ class Warpy(SimpleCommandPlugin): """ name = "warpy_plugin" depends = ['command_dispatcher', 'player_manager'] - commands = ["warp", "warp_ship"] + commands = ["warp", "warp_ship", "outpost"] auto_activate = True def activate(self): super(Warpy, self).activate() self.player_manager = self.plugins['player_manager'].player_manager + ## Warp debugging + #def on_warp_command(self, data): + # self.logger.debug("Warp packet: %s", data.data.encode('hex')) + # warp_data = warp_command().parse(data.data) + # self.logger.debug("Warp packet: %s", warp_data) + @permissions(UserLevels.ADMIN) def warp(self, name): """Warps you to a player's ship (or player to player).\nSyntax: /warp [player] (to player)""" @@ -38,6 +45,7 @@ def warp(self, name): return self.warp_player_to_player(first_name, second_name) +# THIS IS CURRENTLY BROKEN! @permissions(UserLevels.ADMIN) def warp_ship(self, location): """Warps a player ship to another players ship.\nSyntax: /warp_ship [player] (to player)""" @@ -58,6 +66,20 @@ def warp_ship(self, location): self.protocol.send_chat_message(str(e)) return self.move_player_ship_to_other(first_name, second_name) +#!!!!!!!!!!!!!!!!!!!!!!! + + @permissions(UserLevels.ADMIN) + def outpost(self, name): + """Warps you (or another player) to the outpost.\nSyntax: /outpost [player]""" + if len(name) == 0: + self.warp_player_to_outpost(self.protocol.player.name) + else: + try: + player_name, rest = extract_name(name) + except ValueError as e: + self.protocol.send_chat_message(str(e)) + return + self.warp_player_to_outpost(player_name) def warp_self_to_player(self, name): self.logger.debug("Warp command called by %s to %s", self.protocol.player.name, name) @@ -73,12 +95,14 @@ def warp_player_to_player(self, from_string, to_string): if to_player is not None: from_protocol = self.factory.protocols[from_player.protocol] if from_player is not to_player: + self.logger.debug("target: %s", to_player.uuid) warp_packet = build_packet(Packets.PLAYER_WARP, - warp_command_write(t="WARP_OTHER_SHIP", - player=to_player.org_name.encode('utf-8'))) + warp_command_write(t="WARP_TO", + world_id=to_player.uuid)) else: warp_packet = build_packet(Packets.PLAYER_WARP, - warp_command_write(t='WARP_UP')) + warp_command_write(t="WARP_TO_OWN_SHIP", + world_id=None)) from_protocol.client_protocol.transport.write(warp_packet) if from_string != to_string: self.protocol.send_chat_message("Warped ^yellow;%s^green; to ^yellow;%s^green;." % (from_string, to_string)) @@ -140,3 +164,17 @@ def move_player_ship_to_other(self, from_player, to_player): self.move_player_ship(self.factory.protocols[f.protocol], t.planet.split(":")) self.protocol.send_chat_message("Warp drive engaged. Warping ^yellow;%s^green; to ^yellow;%s^green;." % (from_player, to_player)) + def warp_player_to_outpost(self, player_string): + self.logger.debug("Warp player-to-outpost command called by %s: sending %s to the outpost", self.protocol.player.name, player_string) + player_to_send = self.player_manager.get_logged_in_by_name(player_string) + if player_to_send is not None: + player_protocol = self.factory.protocols[player_to_send.protocol] + warp_packet = build_packet(Packets.PLAYER_WARP, + warp_command_write(t="WARP_TO", + world_id="outpost")) + player_protocol.client_protocol.transport.write(warp_packet) + self.protocol.send_chat_message("Warped ^yellow;%s^green; to the outpost." % player_string) + else: + self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % player_string) + self.protocol.send_chat_message(self.warp.__doc__) + diff --git a/server.py b/server.py index b89a9f9..9de9910 100644 --- a/server.py +++ b/server.py @@ -148,7 +148,7 @@ def string_received(self, packet): """ if 53 >= packet.id: # DEBUG - print all packet IDs going to client - #logger.info("%s", packet.id) + # logger.info("From Client: %s", packet.id) if self.handle_starbound_packets(packet): self.client_protocol.transport.write( packet.original_data) @@ -521,6 +521,8 @@ def string_received(self, packet): :return: None """ try: + # DEBUG - print all packet IDs coming from client + # logger.info("From Server: %s", packet.id) if self.server_protocol.handle_starbound_packets( packet): self.server_protocol.write(packet.original_data) diff --git a/utility_functions.py b/utility_functions.py index 86d11a9..562ec65 100644 --- a/utility_functions.py +++ b/utility_functions.py @@ -65,7 +65,7 @@ def move_ship_to_coords(protocol, x, y, z, planet, satellite): ":".join((str(x), str(y), str(z), str(planet), str(satellite)))) x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) warp_packet = build_packet(packets.Packets.WARP_COMMAND, - packets.warp_command_write(t="MOVE_SHIP", x=x, y=y, z=z, + packets.warp_command_write(t="WARP_TO", x=x, y=y, z=z, planet=planet, satellite=satellite, player="".encode('utf-8'))) protocol.client_protocol.transport.write(warp_packet) From e5e1b2cf18868730b33022bea932abbfd997f3e1 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Thu, 8 Jan 2015 02:43:14 -0500 Subject: [PATCH 56/95] small correction --- utility_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility_functions.py b/utility_functions.py index 562ec65..a8eb265 100644 --- a/utility_functions.py +++ b/utility_functions.py @@ -38,7 +38,7 @@ def recursive_dictionary_update(d, u): def build_packet(packet_type, data): """ Convenience method to build packets for sending. - :param packet_type: An integer 1 <= packet_type <= 48 + :param packet_type: An integer 1 <= packet_type <= 53 :param data: Data to send. :return: The build packet. :rtype : str From 47538b916fbee1873598d14385a3d37a048500ec Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 31 Jan 2015 01:45:28 -0500 Subject: [PATCH 57/95] Removed unnecessary plugin (UDP), unnecessary/old folder (test), and fixed client crash on first connect to server (resulting from give item) --- plugins/UDPForwarder/UDPForwarder.py | 32 --- plugins/UDPForwarder/__init__.py | 1 - .../starbound_config_manager.py | 8 +- .../new_player_greeter_plugin.py | 3 +- tests/__init__.py | 0 tests/large_packets.json | 4 - tests/packet_tests.py | 227 ------------------ 7 files changed, 6 insertions(+), 269 deletions(-) delete mode 100644 plugins/UDPForwarder/UDPForwarder.py delete mode 100644 plugins/UDPForwarder/__init__.py delete mode 100644 tests/__init__.py delete mode 100644 tests/large_packets.json delete mode 100644 tests/packet_tests.py diff --git a/plugins/UDPForwarder/UDPForwarder.py b/plugins/UDPForwarder/UDPForwarder.py deleted file mode 100644 index c02579d..0000000 --- a/plugins/UDPForwarder/UDPForwarder.py +++ /dev/null @@ -1,32 +0,0 @@ -from twisted.internet import reactor -from twisted.internet.error import CannotListenError -from twisted.internet.protocol import DatagramProtocol - -from base_plugin import BasePlugin - - -class UDPForwader(BasePlugin): - """Forwards UDP datagrams to the gameserver, mostly used for Valve's Steam style statistis queries""" - name = "udp_forwarder" - auto_activate = True - - def activate(self): - - super(UDPForwader, self).activate() - try: - reactor.listenUDP(self.config.bind_port, UDPProxy(self.config.upstream_hostname, self.config.upstream_port), interface=self.config.bind_address) - self.logger.info("Listening for UDP on port %d" % self.config.bind_port) - except CannotListenError: - self.logger.error( - "Could not listen on UDP port %d. Will continue running, but please note that steam statistics will be unavailable.", - self.factory.config.bind_port - ) - - -class UDPProxy(DatagramProtocol): - def __init__(self,upstream_hostname, upstream_port): - self.upstream_hostname = upstream_hostname - self.upstream_port = upstream_port - - def datagramReceived(self, datagram, addr): - self.transport.write(datagram, (self.upstream_hostname, self.upstream_port)) diff --git a/plugins/UDPForwarder/__init__.py b/plugins/UDPForwarder/__init__.py deleted file mode 100644 index 47aadc5..0000000 --- a/plugins/UDPForwarder/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from UDPForwarder import UDPForwader diff --git a/plugins/core/starbound_config_manager/starbound_config_manager.py b/plugins/core/starbound_config_manager/starbound_config_manager.py index 96f980d..b82a2a2 100644 --- a/plugins/core/starbound_config_manager/starbound_config_manager.py +++ b/plugins/core/starbound_config_manager/starbound_config_manager.py @@ -13,7 +13,7 @@ class StarboundConfigManager(SimpleCommandPlugin): def activate(self): super(StarboundConfigManager, self).activate() try: - configuration_file = FilePath(self.config.starbound_path).child('starbound_server.config') + configuration_file = FilePath(self.config.starbound_path).child('starbound.config') if not configuration_file.exists(): raise FatalPluginError( "Could not open starbound configuration file. Tried path: %s" % configuration_file) @@ -26,10 +26,10 @@ def activate(self): raise FatalPluginError( "Could not parse the starbound configuration file as JSON. Error given from JSON decoder: %s" % str( e)) - if self.config.upstream_port != starbound_config['gamePort']: + if self.config.upstream_port != starbound_config['gameServerPort']: raise FatalPluginError( - "The starbound gamePort option (%d) does not match the config.json upstream_port (%d)." % ( - starbound_config['gamePort'], self.config.upstream_port)) + "The starbound gameServerPort option (%d) does not match the config.json upstream_port (%d)." % ( + starbound_config['gameServerPort'], self.config.upstream_port)) #self._spawn = starbound_config['defaultWorldCoordinate'].split(":") self._spawn = "junk" diff --git a/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py b/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py index a97e6e3..16f0121 100644 --- a/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py +++ b/plugins/new_player_greeter_plugin/new_player_greeter_plugin.py @@ -1,3 +1,4 @@ +from twisted.internet import reactor, defer from base_plugin import BasePlugin from utility_functions import give_item_to_player @@ -12,7 +13,7 @@ class NewPlayerGreeter(BasePlugin): def activate(self): super(NewPlayerGreeter, self).activate() - def after_connect_response(self, data): + def after_world_start(self, data): if self.protocol.player is not None and self.protocol.player.logged_in: my_storage = self.protocol.player.storage if not 'given_starter_items' in my_storage or my_storage['given_starter_items'] == "False": diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/large_packets.json b/tests/large_packets.json deleted file mode 100644 index 597ff0b..0000000 --- a/tests/large_packets.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "client_connect": "202caf2f18a03c02d5baa3321f01f1970a66769e1c27fe1b2993fb334be580a3b90101d3d1bc89462baa6f872b1d179c749a220e416e6b684d6f72706f726b69616e06676c697463688ce800534242463031000004000000020001000000000000009000000000000000000042544442303100000000000000000187000e0957524c444256312e31000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000172000e0957524c444256312e31000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004646ffffffffffffffff0000003e000000000000004f0000000000000050000000000000005200000000000000540000000000000055000000000000005600000000000000570000000000000058000000000000005a0000000000000063000000000000006400000000000000650000000000000066000000000000006700000000000000680000000000000069000000000000006a000000000000006c000000000000006f00000000000000700000000000000072000000000000007700000000000000780000000000000079000000000000007a000000000000007b000000000000007c000000000000007e000000000000008100000000000000830000000000000183000000000000018800000000000000a700000000000001530000000000000126000000000000008e0000000000000133000000000000009e0000000000000141000000000000001b00000000000001420000000000000150000000000000007f00000000000000b400000000000000ec0000000000000104000000000000015c0000000000000161000000000000014a000000000000012f000000000000017b000000000000018d00000000000000db0000000000000075000000000000014c00000000000000b100000000000000e800000000000000890000000000000131000000000000018a000000000000015b000000000000016b01374c4c00000005010010001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010010001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000000054c4c00000007010009001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010009001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901000a000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000c04c4c00000004010004001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c04070000021b00000204811b0000021c00000204070000021d00000204070000021e00000204070000021f00000204070000022000000204070000022100000204070000022200000204811b0000022300000204070000022400000204070000022500000204070000022600000204070000022700000204070000022800000204070000022900000204811b0000022a00000204070000022b00000204070000022c00000204070000022d00000204070000022e00000204070000022f00000204070000023000000204811b0000023100000204070000023200000204070000023300000204070000023400000204070000023500000204070000023600000204070000023700000204070000023800000204070000023900000204070000023a00000204070000023b00000204070000023c00000204070000023d00000204070000023e00000204077f0000020a0000020d070000020b0000020d070000020c0000020d070000020d0000020d070000020e0000020d070000020f0000020d07000002100000020d07000002110000020d07000002120000020d07000002130000020d07000002140000020d07000002150000020d07000002160000020d07000002170000020d07000002180000020d07000002190000020d070000021a0000020d070000021b0000020d070000021c0000020d0700000000000000de4c4c18638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010017000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000801001c001160789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001c001260789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001c001360789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001c001460789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001d000060789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618000000000000010d4c4c0000000401000d001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000002f020005001309789c63000000010001020005001409789c63000000010001020005001509789c63000000010001020005001609789c63000000010001020005001709789c63000000010001020006000009789c63000000010001020006000109789c63000000010001020006000209789c63000000010001020006000309789c63000000010001020006000409789c63000000010001020006000509789c63000000010001020006000609789c63000000010001020006000709789c63000000010001020006000809789c63000000010001020006000909789c63000000010001020006000a09789c63000000010001020006000b09789c63000000010001020006000c09789c63000000010001020006000d09789c63000000010001020006000e09789c63000000010001020006000f09789c63000000010001020006001009789c63000000010001020006001109789c63000000010001020006001209789c63000000010001020006001309789c63000000010001020006001409789c63000000010001020006001509789c63000000010001020006001609789c63000000010001020006001709789c63000000010001020006001809789c63000000010001020007000009789c63000000010001020007000109789c63000000010001020007000209789c63000000010001020007000000000000001d4c4c09789c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010006000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0001020011001609789c63000000010001020011001709789c63000000010001020011001809789c63000000010001020012000009789c63000000010001020012000109789c63000000010001020012000209789c63000000010001020012000309789c63000000010001020012000409789c63000000010001020012000509789c63000000010001020012000609789c63000000010001020012000709789c63000000010001020012000809789c63000000010001020012000909789c63000000010001020012000a09789c63000000010001020012000b09789c63000000010001020012000c09789c63000000010001020012000d09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000201000a000f811f789cedd4410a83301005d040361ec63b66e1b58558c552eca222d838ca0b8461de2e339f0c7dae35a5d75dcb7c968231c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6d772eaca96731dffcc711e8f1fcff21d997f0f369523dc72c571f8dd97cf601b7180f884e733f31d87e5fbb97c97ed60f93e3fdfdf1f5eb8a5e17d9e0040d344a101000a0010816b789ceddb410a83301005d0809b1ea677cca2d716522c9582a868ab76340f14f10926137f36213eee4dbae5544a77bcce949ad276972ab8bfcf3d277c318e13b603f853bc7c638c31c618638c31c618638c31c618638c31c618638c8fe189ed4b7635e14bb07ce32bb37ce320dc3f7d8b7ce3e03c91d885bcee8780795ef89252f27839a3fc55939bf0bae2ebe0df06365cbe77e1b3e4fbc839bf659501821c27df7f982471fabd2fe721b7731ca7df78c8f22ddf41b9f20c1e3eb03804c7c9c95939ceb7ac9ae30402638c31c618638c31c6cb390f7976597c1dc7a9320ac759c9c11863bc869f3e466469000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000d00108169789cedd5db0a82401405d0015ffa98fe711efaedc02e68505034ead471660921adc0ced96ef1741cc631a5eb673add8efb09638c71704e87fcccc378c638e5128e33771c2e4b50b0bfad669c8bace3f9fbe32f13c66f5fff7106c418638c31c618638c31c618638cbbe65cc471e6c678fbc6963d0d1e121ca255f3af932ce338ebe076aa59d6d89afd5e5bfbb26be7575e1c6ccde523f3a704bfe638ebe0766ef15ee7fe43267106dc2b6f52b6aeabb949b071e6de2bd7ac661fb5ef634bc1b6b3656309f671d3ba66c1568a4a825835312e61d5c418638c31c618638c31c61863dc1e5f00b36d4a5e01000d00117d789cedce310a80300c05d040170fe31d3b786d216a2d8882e0e020f802e193970c99c69219b1768fad5a608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c5fe018ea994bce6d57afd7dfe29bbf31c6f837dce783f7c018638c31c618638c31c618638c31c618638c31c6f8112fcba18ae10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c1b37b3be7133eb1b638c31c618638c31c61863fc0d5f01fd6df61c01000b00128115789cedd23b0a80301045d1808d8b718f166e5b881f6c2c2cd414fa380361e05419b8d3d0d55acafa8eb5cdbe30c618638c31c618638c31c618638c31c61863fc844b3f9eb9abf3a73e88f10bd637fe175f142b641cc1fac6c9ac6f9cccfac6ff62c5e264d6374e667de364d6374e667de364d6374ee67b7d37e1ef1c8fe359df18638c31c618638c31c618638c71135e000440ac1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000a000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010014000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000884c4c0000000301000a00118109789cedd23b0a80301045d180db718f166e3b103f58052cec1ee3190803a7cac0ddd7658cd6cef7ac6bee8531c618638c31c618638c31c618638c31c618638c31c618e31abccddcc33e88ffca2f697ee39c73701d96260e6569e25096260e6569e25096260e6569e25096260e6569e25096262ec1d2c418638c31c618638c31c618635c8f0f5ec0ea7c01000a00128103789cedd73b0a80400c40c1c0361ec63b5a786d217eb0b1b2126298c012986ee13559e7911971bc7b9d732d8c31c618638c31c618638c31c618638c31c618638c31c618638c31c6c538a6e5c923b78fb9cee7717bd637c62fac6fdc99f58d3bb3be7167d6372ecaee4bdc99f58d31c618638c31c618638c31c61863fc2fde01f066b1f801000a00138111789cedd63b0a80301005c0808d87f18e165e5b881fb4b0122ce4196761599832fb16320d5dada5ac7d8cadf68131c6389c4b3f5eb9abf38739e7617104e74453be31be6197865b66f9c6f80d760db865966f8c4fcef95735c6392bfe35e704a231ce5931c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61863fc9c17a4347d3c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010017000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000002a4c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010002000960789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000dd4c4c0000000401000e000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e00108210789cedd55d6a8350148551212f1d43c6d039de874e5b306d4d0249488b70ccdd9a2588b884e3df877e7d1ea66918bed7f3e667f9dd608c310ee7e1a3ddf2611a31c618afcb6dde9f8ffecbc799dbed90cbd02b0f182fe0b622e7dc25de0f4b1387b2347128fbcfe3505e334dc5e2de6996ccce792638823b7c07158b43d3542cde569a8ac5bb0822fe02f17bf0e5e8599e73bbe7f12f7e1882b7cead82979cb273b14f66f77e0d788fbc66b1cb38e799e0cdf24b8bd537eecd00000000000000ce4c4c31c618638c3fb8015324dafc010010000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000e001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4cfc010008001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010008001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010013000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000be4c4c9c6300000001000102000a000b09789c6300000001000102000a000c09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000901000e000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000015f4c4c000309789c63000000010001020007000409789c63000000010001020007000509789c63000000010001020007000609789c63000000010001020007000709789c63000000010001020007000809789c63000000010001020007000909789c63000000010001020007000a09789c63000000010001020007000b09789c63000000010001020007000c09789c63000000010001020007000d09789c63000000010001020007000e09789c63000000010001020007000f09789c63000000010001020007001009789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4ce2d2ebdf1308813325f00d77c9fa98f6bdb5d7fe1cef751c3fe1a5e7ed02d7790ece6169e2a22c4d8c31c618638c31c618638c31c618638c31c618638c31c618638c31c6189f78e9f9ca678331aef3781ccffac6c92c4d9cccfac6c9ac6f9ccb6dee429e8e90bf709d7be37fe5b162f58defc6631387f904df8b158b9359df3899f58d9359df3899f58d93b978df4f901de60e01000c00128139789cedda410a83301040d1809b1ec63bbae8b50bb196bae8428818613a798204de2a307f7679ce53ada5bcffefb17d9f03e3162e8fe597a7fa3ae638f7c6b885f58dff8b158b33b3be7166d637ceccfa1e95cf4d7e0c8e331daceffe1c673a6639ea2cb1be5b38ce74f0d590e35c10e30bac6f8c31c618638c31c618638c31c618638c31c6f87e8ef37cc98b29dc9fe3c4a66f8cbbb26dc09959df18ef6c1b7066d637ceccfac69959df18ef6c1b7066d677085e019f82488000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010005000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000224c4c18638c31c6f8830fc493e2f9010001000760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000000010000000000af2e000004410000040faf24000001ac4403800044014000845a000004410000040f844600000000000000000000000000000000000000000000000000000000000000000042a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000494c4c31c618638c3fb8015324dafc010005000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000a001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000000040100100011811f789cedd4410a83301040d1816c728b5ec03b76d16b0ba94aa14410845619f40542e09145203f790da5b588697e96792c0bc618638c31c618638c31c618638cefc1519f3d9736e2641cf5d1719e7cd273babbc47bfa5eed0ebcc9595e1adee46fdff9f2398efff243a4bb4bbca7ef6407c4f807d637be32eb1b638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3f3f80d0f509efb010010001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010003001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010003001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010004000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000004b49490000000017000000000000014b01001100130000000000000181010012000200000000000000d9010012000b0000000000000182010012000e00000000000001650100120011000000000000011001001200150000000000000160010013000000000000000001300100130006000000000000001a010013000c00000000000000ab010013000f00000000000000470100130012000000000000011b010013001500000000000000d20100140000000000000000005e01001400060000000000000011010014000c000000000000011a010014000f000000000000008b010014001100000000000000cf01001400150000000000000174010015000100000000000000af01001500070000000000000176010015000d000000000000009001001500130000000000000122010015001700000000000000ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c00010001020008001609789c63000000010001020008001709789c63000000010001020008001809789c63000000010001020009000009789c63000000010001020009000109789c63000000010001020009000209789c63000000010001020009000309789c63000000010001020009000409789c63000000010001020009000509789c63000000010001020009000609789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000f001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01000f001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010010000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c030011696e76696e6369626c65506c61796572730301086675656c2e6d6178048f500a6675656c2e6c6576656c04892a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010017000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000001f020009000709789c63000000010001020009000809789c63000000010001020009000909789c63000000010001020009000a09789c63000000010001020009000b09789c63000000010001020009000c09789c63000000010001020009000d09789c63000000010001020009000e09789c63000000010001020009000f09789c63000000010001020009001024789c636ad66116622dc92f4ace6067606060d46160606262644413b585880200aade065a020009001109789c6300000001000102000900121f789c636cd66116622dc92f4ace6067606060d4666060f2616404003374036e02000900131f789c636cd66116622dc92f4ace6067606060346760604a606400003403038d020009001409789c63000000010001020009001509789c63000000010001020009001609789c63000000010001020009001709789c63000000010001020009001809789c6300000001000102000a000009789c6300000001000102000a000109789c6300000001000102000a000209789c6300000001000102000a000309789c6300000001000102000a000409789c6300000001000102000a000509789c6300000001000102000a000609789c6300000001000102000a000709789c6300000001000102000a000809789c6300000001000102000a000909789c6300000001000102000a000a097800000000000000ed4c4c09789c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c020a07000002190000020a070000021a0000020a070000021b0000020a811b0000021c0000020a070000021d0000020a070000021e0000020a070000021f0000020a07000002200000020a07000002210000020a07000002220000020a811b000002230000020a07000002240000020a07000002250000020a07000002260000020a07000002270000020a07000002280000020a07000002290000020a811b0000022a0000020a070000022b0000020a070000022c0000020a070000022d0000020a070000022e0000020a070000022f0000020a070000020b00000209070000020c00000209070000020d00000209070000020e00000209070000020f00000209070000021000000209070000021100000209811b0000021200000209070000021300000209070000021400000209811b0000021500000209070000021600000209070000021700000209070000021800000209070000021900000209070000021a00000209070000021b00000209811b0000021c00000209070000021d00000209070000021e00000209070000021f00000209070000022000000209070000022100000209070000022200000209811b0000022300000209070000022400000209070000022500000209070000022600000209070000022700000209070000022800000209070000022900000209811b0000022a0000000000000001734c4c00000004010008000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010018000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010018000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000d01001e000560789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000860789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000001294c4c00000029020012000e09789c63000000010001020012000f09789c6300000001000102001200101d789c636cd66116622dc92f4ace60676060607204624e1646003353034502001200111d789c636cd66116622dc92f4ace6067606060f205620346460034160375020012001209789c63000000010001020012001309789c63000000010001020012001409789c63000000010001020012001509789c63000000010001020012001609789c63000000010001020012001709789c63000000010001020012001809789c63000000010001020013000009789c63000000010001020013000109789c63000000010001020013000209789c63000000010001020013000309789c63000000010001020013000409789c63000000010001020013000509789c63000000010001020013000609789c63000000010001020013000709789c63000000010001020013000809789c63000000010001020013000909789c63000000010001020013000a09789c63000000010001020013000b09789c63000000010001020013000c09789c63000000010001020013000d09789c63000000010001020013000e09789c63000000010001020013000f09789c6300000001000102001300102a789c636ed66116622dc92f4ace6067606060ca076239460634d1342066606444134d87880200820f0a3f0200130011000000000000002c4c4c31c618638c3fb8015324dafc01000b000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000003302000a000d09789c6300000001000102000a000e09789c6300000001000102000a000f1d789c636cd66116622dc92f4ace60676060600c07e27f8c8c0036ba044b02000a001009789c6300000001000102000a001109789c6300000001000102000a00121f789c636cd66116622dc92f4ace6067606060746060600a626404003419038902000a00131f789c636cd66116622dc92f4ace60676060600c676060ca62640000350103b702000a001409789c6300000001000102000a001509789c6300000001000102000a001609789c6300000001000102000a001709789c6300000001000102000a001809789c6300000001000102000b000009789c6300000001000102000b000109789c6300000001000102000b000209789c6300000001000102000b000309789c6300000001000102000b000409789c6300000001000102000b000509789c6300000001000102000b000609789c6300000001000102000b000709789c6300000001000102000b000809789c6300000001000102000b000909789c6300000001000102000b000a09789c6300000001000102000b000b09789c6300000001000102000b000c09789c6300000001000102000b000d09789c6300000001000102000b000e09789c6300000001000102000b000f22789c636ad66116622dc92f4ace60676060602c07e23f8c0000000000000192494900000000170000000000000112010004001000000000000000a101000400130000000000000003010004001700000000000000aa0100050007000000000000001f010005000d00000000000001180100050011000000000000003f010005001500000000000001360100050019000000000000009d01000600050000000000000096010006000b00000000000000c7010006001200000000000001320100060015000000000000006b010006001900000000000000f10100070007000000000000004d010007000d0000000000000044010007001200000000000000c2010007001500000000000001690100070019000000000000009b0100080006000000000000012c010008000c000000000000002e0100080010000000000000016d0100080012000000000000017a010009000000000000000000e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c0534ed53b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4ce2d2ebdf1308813325f00d77c9fa98f6bdb5d7fe1cef751c3fe1a5e7ed02d7790ece6169e2a22c4d8c31c618638c31c618638c31c618638c31c618638c31c618638c31c6189f78e9f9ca678331aef3781ccffac6c92c4d9cccfac6c9ac6f9ccb6dee429e8e90bf709d7be37fe5b162f58defc6631387f904df8b158b9359df3899f58d9359df3899f58d93b978df4f901de60e01000c00128139789cedda410a83301040d1809b1ec63bbae8b50bb196bae8428818613a798204de2a307f7679ce53ada5bcffefb17d9f03e3162e8fe597a7fa3ae638f7c6b885f58dff8b158b33b3be7166d637ceccfa1e95cf4d7e0c8e331daceffe1c673a6639ea2cb1be5b38ce74f0d590e35c10e30bac6f8c31c618638c31c618638c31c618638c31c6f87e8ef37cc98b29dc9fe3c4a66f8cbbb26dc09959df18ef6c1b7066d637ceccfac69959df18ef6c1b7066d677085e019f82488000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010000001160789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000001260789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000001360789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000001460789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000801001d000460789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000760789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61800000000000001164c4c0000003302000a000d09789c6300000001000102000a000e09789c6300000001000102000a000f1d789c636cd66116622dc92f4ace60676060600c07e27f8c8c0036ba044b02000a001009789c6300000001000102000a001109789c6300000001000102000a00121f789c636cd66116622dc92f4ace6067606060746060600a626404003419038902000a00131f789c636cd66116622dc92f4ace60676060600c676060ca62640000350103b702000a001409789c6300000001000102000a001509789c6300000001000102000a001609789c6300000001000102000a001709789c6300000001000102000a001809789c6300000001000102000b000009789c6300000001000102000b000109789c6300000001000102000b000209789c6300000001000102000b000309789c6300000001000102000b000409789c6300000001000102000b000509789c6300000001000102000b000609789c6300000001000102000b000709789c6300000001000102000b000809789c6300000001000102000b000909789c6300000001000102000b000a09789c6300000001000102000b000b09789c6300000001000102000b000c09789c6300000001000102000b000d09789c6300000001000102000b000e09789c6300000001000102000b000f22789c636ad66116622dc92f4ace60676060602c07e23f8c00000000000001234c4c31c618638c3fb8015324dafc01000d000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000d00108169789cedd5db0a82401405d0015ffa98fe711efaedc02e68505034ead471660921adc0ced96ef1741cc631a5eb673add8efb09638c71704e87fcccc378c638e5128e33771c2e4b50b0bfad669c8bace3f9fbe32f13c66f5fff7106c418638c31c618638c31c618638cbbe65cc471e6c678fbc6963d0d1e121ca255f3af932ce338ebe076aa59d6d89afd5e5bfbb26be7575e1c6ccde523f3a704bfe638ebe0766ef15ee7fe43267106dc2b6f52b6aeabb949b071e6de2bd7ac661fb5ef634bc1b6b3656309f671d3ba66c1568a4a825835312e61d5c418638c31c618638c31c61863dc1e5f00b36d4a5e01000d00117d789cedce310a80300c05d040170fe31d3b786d216a2d8882e0e020f802e193970c99c69219b1768fad5a608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c5fe018ea994bce6d57afd7dfe29bbf31c6f837dce783f7c018638c31c618638c31c618638c31c618638c31c6f8112fcba18ae10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000701001d001060789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001d001160789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000060789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000160789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000260789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000001284c4c0206070000021400000206811b0000021500000206070000021600000206070000021700000206070000021800000206070000021900000206070000021a00000206070000021b00000206811b0000021c00000206070000021d00000206070000021e00000206070000021f00000206070000022000000206070000022100000206070000022200000206811b0000022300000206070000022400000206070000022500000206070000022600000206070000022700000206070000022800000206070000022900000206811b0000022a00000206070000022b00000206070000022c00000206070000022d00000206070000022e00000206070000022f00000206070000023000000206811b0000023100000206070000023200000206070000023300000206070000023400000206070000023500000206070000023600000206070000023700000206070000023800000206070000023900000206070000023a00000206070000023b00000206070000023c00000206070000023d00000206070000020b00000205070000020c00000205070000020d00000205070000020e00000205070000020f00000205070000021000000205070000021100000205811b0000021200000205070000021300000205070000021400000205811b000002150000020507000002160000020507000002170000000000000000014e4c4c00000004010005001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000028020007001109789c63000000010001020007001209789c63000000010001020007001309789c63000000010001020007001409789c63000000010001020007001509789c63000000010001020007001609789c63000000010001020007001709789c63000000010001020007001809789c63000000010001020008000009789c63000000010001020008000109789c63000000010001020008000209789c63000000010001020008000309789c63000000010001020008000409789c63000000010001020008000509789c63000000010001020008000609789c63000000010001020008000709789c63000000010001020008000809789c63000000010001020008000909789c63000000010001020008000a09789c63000000010001020008000b09789c63000000010001020008000c09789c63000000010001020008000d09789c63000000010001020008000e09789c63000000010001020008000f09789c63000000010001020008001027789c636ad66116622dc92f4ace6067606060646460609261644013e5018ab231320200a727061b02000800111f789c636cd66116622dc92f4ace6067606060e4606060b26064040032430337020008001209789c63000000010001020008001309789c63000000010001020008001409789c63000000010001020008001509789c63000000000000000000274c4c00000002010009000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000301000b000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000701000d000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000ea4c4c00000005010007000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000700108164789ceddc4b0a83300045d180932ea67b74d06d17d20f2dc50e042525e9f308221c10315c242a7a394fb596725f5f9bc7f2dc60dc9bcb695ef254af9b799cd3c178c1fac6bdb94983eb6996f973c8dd3cc050e13fe45d217f1a5ce5f7defac6bdb8df1559dff8f7ac6f9cccfac6c9ac6f9cccfac6c9ac6f9cccfac6c9ac6f9cccdb5ee4d4fac5a525eb1beb7bb411c423f3d6bed71a343fc1a3b1be7132eb1b27b3e7273899f58d9359df3899f58d93d9fd254e667de364363f000000000000009a4c4c0000000401000b000f8104789cedd24b0a80300c05c040371ec63b76e1b585fa41110fd00f6502e191d905deb6a65222ce7de29a3b30c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3793896fce754f6ca3ccef3787aeed06f8c9bf17be7aff6b5799ce7f1f4dca1df18638c31c618e3767c001390ad1901000b00108135789cedd8bb0a83300086d1804b1fa6ef98a1af5d482fb108999ac192fe1c41a2c70c2a1f1972bb6ead95f23a6b1f9e47bb977e8d31c618638c31c618638c31c618638c31c618638cff943f4f77f905aff3f1f8a420d679137d7ffd6397af0ae7b0d830c6f814ae235b1e7110eb1b27b3be71040b1927b3be7132eb1b27f34cdfe532ccdedeb331c6182fcefbfdc17dc07859ae230b1907b1be7132eb1b27b3be7132eb1b27f34cdfebece4608c319ee10780d0b3dd01000b0011813f789cedd24d0ac2301485d182db718f0edcb6507f70240a7650bdb939851038a3d7bcef7c3cacebb2dccef3ba7f8f0be3583ebdf2256c408cf58df15bd637aee00f216fe39cdfc13dbc679a42c6a169ee3960ce0be2df6e3e274d7dcfca73a4a9ef01599a11ef9d33600e4b73409e630dd29c95e377294d1cdab734f1bf795b55d2c463b1347133eb1b37b3be7133eb1b37b3be7133eb1b37b3be7133eb1b37b3be7133eb000000000000000f4c4c0000000501001a001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a001360789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001a001460789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001a001560789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001a001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000001854c4c00000003010013000f810f789cedd23b0a80301404c0401a0fe31d2dbcb6103f68612582c546261016a6dcb7f3585b2b65fb67ecef088c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ee6324c77ae6de988afb838a7581cc1718b7dc73fdf775cdfdd71ce2db17d7fcf39b73488df5f07dbf78d738ac511bc023cd97a4e0100130010811e789cedd2310ac2501045d10f695c8c7b4ce1b685af09361616c1c2bce71918064e35c5bd5d9739c778eeeb6cb31f8c31c618638c31c618638c31c618638c31c618638c31fe1f1e97f59d97793fd583187fc1fac659fca15821e30ad637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637fe351f6b50b1388bf55dcf0f3bb69d7601001300118109789cedd23b0a80400c40c1856d3c8c77b4f0da42fc606321586ee2044260aa146f9d7b446bc7dee79ceb64e5362d4feeb1bdf3387f63fc85f58d73b1627165d637cec58ac59559df38172b1657667de35cac585c99f58d4bb0627165d637c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6ffe11ddb70bac2000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010016000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000004a4c4c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000447a000000000000000000000000000000000000000000000000000000000000000000b97c2fea48417a810000a97f00000f0000022c0000020111736d616c6c626f6f73746572666c616d650007010b756e627265616b61626c650300000002210000020111736d616c6c626f6f73746572666c616d650007010b756e627265616b61626c650300000002150000020111736d616c6c626f6f73746572666c616d650007010b756e627265616b61626c650300000002390000020411617065786361707461696e7363686169720007010b756e627265616b61626c65030000000231000002040c6170657873686970646f6f720007000000020e000002040a74656c65706f727465720007010b756e627265616b61626c6503000000022d000002060b7465636873746174696f6e0007010b756e627265616b61626c65030000000218000002060e61706578736869706c6f636b65720007030d7472656173757265506f6f6c7306010515676c69746368537461727465725472656173757265056c6576656c04020b756e627265616b61626c65030000000235000000000000000001754c4c31c618638c3fb8015324dafc010016000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010004000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010013000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010007000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000018f4c4c0000003902001a000c09789c6300000001000102001a000d09789c6300000001000102001a000e09789c6300000001000102001a000f09789c6300000001000102001a001009789c6300000001000102001a001109789c6300000001000102001a001209789c6300000001000102001a001309789c6300000001000102001a001409789c6300000001000102001b000009789c6300000001000102001b000109789c6300000001000102001b000209789c6300000001000102001b000309789c6300000001000102001b000409789c6300000001000102001b000509789c6300000001000102001b000609789c6300000001000102001b000709789c6300000001000102001b000809789c6300000001000102001b000909789c6300000001000102001b000a09789c6300000001000102001b000b09789c6300000001000102001b000c09789c6300000001000102001b000d09789c6300000001000102001b000e09789c6300000001000102001b000f09789c6300000001000102001b001009789c6300000001000102001b001109789c6300000001000102001b001209789c6300000001000102001b001309789c6300000001000102001c000009789c6300000001000102001c000109789c6300000001000102001c000209789c6300000001000102001c000309789c6300000001000102001c00000000000001454c4c00000009010011001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000b24c4c0000000401000b0013810b789cedd23b0a80400c45d181695c8c7bb470db42fc60a39dddc3398110385de0ae73af6aedd8fb9c731d8c31c618638c31c6e3709b9627f7da3e73ce3b183f58df38b42a69e250fe59df39efc473d58b5b18e75495c339f9c4734ec8fac618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c87e21d23a6988601000b001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010002000360789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000460789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000760789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61800000000000000534c4c00000023020014000509789c63000000010001020014000609789c63000000010001020014000709789c63000000010001020014000809789c63000000010001020014000909789c63000000010001020014000a09789c63000000010001020014000b09789c63000000010001020014000c09789c63000000010001020014000d09789c63000000010001020014000e09789c63000000010001020014000f09789c6300000001000102001400101d789c636cd66116622dc92f4ace60676060606a076206464600351c037f020014001109789c63000000010001020014001209789c63000000010001020014001309789c63000000010001020014001409789c63000000010001020014001509789c63000000010001020014001609789c63000000010001020014001709789c63000000010001020014001809789c63000000010001020015000009789c63000000010001020015000109789c63000000010001020015000209789c63000000010001020015000309789c63000000010001020015000409789c63000000010001020015000509789c63000000010001020015000609789c63000000010001020015000709789c63000000010001020015000809789c63000000010001020015000909789c63000000010001020015000a09789c63000000010001020015000b09789c630000000100000000000000554c4c638c31c618e30f6eca34eafb010002000860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0001020015000c09789c63000000010001020015000d09789c63000000010001020015000e09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010016000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010012000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000f73789cedd2310a80301004c083343e267fb4c8b7854b2236e91502cec2b130ed6dab253362dc533377618c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f85b8ee35cb9e4f51bdee70dd8bedfe70e9caabac201001200108159789cedd84d0a83301446d18050ba86aea17b74d06d17d21f1cb4410a81809ff508229c81a8ef46c4db75aab594e7be1c5edbfb90c3e53c7ff354efb887736689f53d9e7366299fb5e9cced75ffe494078b23b85cca692db63e9e9b730fe495ebeee3ace78d37e125aeb693bdf2e75d5a0d3828cdccd5103934acef4d1649e4880fcd399dec95736689f5adef63714e27f19c3334ac6f21e3a8aa848cc7734e6cfe68e3f19c13b2772c1ecf8ac5ffccc3bf0a848c43599a18638c31c618638c31c618638c31c618638c31c618638c31c618631cc80f310beafd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000001602001000111d789c636cd66116622dc92f4ace60676060606204621d46060031f50324020010001209789c63000000010001020010001309789c63000000010001020010001409789c63000000010001020010001509789c63000000010001020010001609789c63000000010001020010001709789c63000000010001020010001809789c63000000010001020011000039789c636cd661d117e44d2acdcb4e2d2ac82f2e492d3262626770e1b22ab06f9f50c3000487e6868639372c9d7548eb6e0288cf000090840f60020011000109789c63000000010001020011000209789c63000000010001020011000309789c63000000010001020011000409789c63000000010001020011000509789c63000000010001020011000609789c63000000010001020011000709789c63000000010001020011000809789c63000000010001020011000909789c63000000010001020011000a09789c63000000010001020011000b09789c63000000010001020011000c09789c63000000010001020011000d09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000701000a000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000006d4c4c000309789c63000000010001020017000409789c63000000010001020017000509789c63000000010001020017000609789c63000000010001020017000709789c63000000010001020017000809789c63000000010001020017000909789c63000000010001020017000a09789c63000000010001020017000b09789c63000000010001020017000c09789c63000000010001020017000d09789c63000000010001020017000e09789c63000000010001020017000f09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010007000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010002000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010014000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001434c4c0000000601001b000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001464c4c0000000801000b001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01000b001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901000c000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000011d4c4c638c31c618e30f6eca34eafb01001b001160789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010002001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010002001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010018000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010017001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010017001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010018000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c1d42d6377e19eb1bef9973fa963daee79c90658feb39a758d9e37ace491347704e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9acbf90462c5a64600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000005010012001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010012001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6000000000000007f4c4c00000028020007001109789c63000000010001020007001209789c63000000010001020007001309789c63000000010001020007001409789c63000000010001020007001509789c63000000010001020007001609789c63000000010001020007001709789c63000000010001020007001809789c63000000010001020008000009789c63000000010001020008000109789c63000000010001020008000209789c63000000010001020008000309789c63000000010001020008000409789c63000000010001020008000509789c63000000010001020008000609789c63000000010001020008000709789c63000000010001020008000809789c63000000010001020008000909789c63000000010001020008000a09789c63000000010001020008000b09789c63000000010001020008000c09789c63000000010001020008000d09789c63000000010001020008000e09789c63000000010001020008000f09789c63000000010001020008001027789c636ad66116622dc92f4ace6067606060e4616060626364441365048aca30320000a64b061b02000800111f789c636cd66116622dc92f4ace6067606060e4606060b26064040032430337020008001209789c63000000010001020008001309789c63000000010001020008001409789c63000000010001020008001509789c63000000000000000000e64c4c00000029020012000e09789c63000000010001020012000f09789c6300000001000102001200101d789c636cd66116622dc92f4ace60676060607204624e1646003353034502001200111d789c636cd66116622dc92f4ace6067606060f205620346460034160375020012001209789c63000000010001020012001309789c63000000010001020012001409789c63000000010001020012001509789c63000000010001020012001609789c63000000010001020012001709789c63000000010001020012001809789c63000000010001020013000009789c63000000010001020013000109789c63000000010001020013000209789c63000000010001020013000309789c63000000010001020013000409789c63000000010001020013000509789c63000000010001020013000609789c63000000010001020013000709789c63000000010001020013000809789c63000000010001020013000909789c63000000010001020013000a09789c63000000010001020013000b09789c63000000010001020013000c09789c63000000010001020013000d09789c63000000010001020013000e09789c63000000010001020013000f09789c63000000010001020013001028789c636ed66116622dc92f4ace60676060604a076206464634d134aca2f9402cc7c800007bb30a3f0200130011097800000000000000d14c4c00000004010016000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010006001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006001760789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010006001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000023020014000509789c63000000010001020014000609789c63000000010001020014000709789c63000000010001020014000809789c63000000010001020014000909789c63000000010001020014000a09789c63000000010001020014000b09789c63000000010001020014000c09789c63000000010001020014000d09789c63000000010001020014000e09789c63000000010001020014000f09789c6300000001000102001400101d789c636cd66116622dc92f4ace60676060606a076206464600351c037f020014001109789c63000000010001020014001209789c63000000010001020014001309789c63000000010001020014001409789c63000000010001020014001509789c63000000010001020014001609789c63000000010001020014001709789c63000000010001020014001809789c63000000010001020015000009789c63000000010001020015000109789c63000000010001020015000209789c63000000010001020015000309789c63000000010001020015000409789c63000000010001020015000509789c63000000010001020015000609789c63000000010001020015000709789c63000000010001020015000809789c63000000010001020015000909789c63000000010001020015000a09789c63000000010001020015000b09789c630000000100000000000001404c4c31c618638c3fb8015324dafc01000a000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000801000c001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01000c001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901000d000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000ef4c4c0000003302000a000d09789c6300000001000102000a000e09789c6300000001000102000a000f1d789c636cd66116622dc92f4ace60676060600c07e27f8c8c0036ba044b02000a001009789c6300000001000102000a001109789c6300000001000102000a00121f789c636cd66116622dc92f4ace6067606060746060600a626404003419038902000a00131f789c636cd66116622dc92f4ace60676060600c676060ca62640000350103b702000a001409789c6300000001000102000a001509789c6300000001000102000a001609789c6300000001000102000a001709789c6300000001000102000a001809789c6300000001000102000b000009789c6300000001000102000b000109789c6300000001000102000b000209789c6300000001000102000b000309789c6300000001000102000b000409789c6300000001000102000b000509789c6300000001000102000b000609789c6300000001000102000b000709789c6300000001000102000b000809789c6300000001000102000b000909789c6300000001000102000b000a09789c6300000001000102000b000b09789c6300000001000102000b000c09789c6300000001000102000b000d09789c6300000001000102000b000e09789c6300000001000102000b000f22789c636ad66116622dc92f4ace60676060602c07e23f8c000000000000009e4c4c0000000301000b000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0207070000020e00000207070000020f00000207070000021000000207070000021100000207811b0000021200000207070000021300000207070000021400000207811b0000021500000207070000021600000207070000021700000207070000021800000207070000021900000207070000021a00000207070000021b00000207811b0000021c00000207070000021d00000207070000021e00000207070000021f00000207070000022000000207070000022100000207070000022200000207811b0000022300000207070000022400000207070000022500000207070000022600000207070000022700000207070000022800000207070000022900000207811b0000022a00000207070000022b00000207070000022c00000207070000022d00000207070000022e00000207070000022f00000207070000023000000207811b0000023100000207070000023200000207070000023300000207070000023400000207070000023500000207070000023600000207070000023700000207070000023800000207070000023900000207070000023a00000207070000023b00000207070000020b00000206070000020c00000206070000020d00000206070000020e00000206070000020f00000206070000021000000206070000021100000206811b000002120000020607000002130000000000000000003e4c4c0000000401000e00118170789cedda410ac2301445d140272ec63d3a70db42d522054752fdd4d7cf2984c01985e40e12e8f53ccdf3188ff19a9edf3261bcf2ad17e76c2c8ee09c34f58deb39274d7de37ace4953dfb89e73d2d437aee79c34f58deb39274d7de37ace4953dfb89e73d2d437aee79c34f58d7fe471babcf3b4747254ced9581cc13969eadbc9ef124433ceaa2a87731ad4b7beeb8bcd59f7ce9c93a6bef55dcf396936ecdbe3e3ef9c93a6bef55dcf39696ee79c878d06f197ac6fdc998f7c3fc1f813eb1b77667de3ceac6fdc99f58d3bb3be7167d637eeccfac69d59dfb833eb1bb7e086ff5761bcb2be7167dedef71d3e457b2f01000e00127e789cedd2310ac020104541c1ebe4965e5b301ad2a44f21df11d685e9165ebbea18a5cc79d77acfc27843ee7ff03ee760fc617de30359df3899f58d9359df3899f58d9359df3899f58d9359df3899f58d9359df18638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3f9ddf90fdab401000e001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e001460789cedc8c10900200c04c100000000000001204c4c0000000901000f001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000284c4c00000003010001001460789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010015001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010015001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000201000a000f811f789cedd4410a83301005d040361ec63b66e1b58558c552eca222d838ca0b8461de2e339f0c7dae35a5d75dcb7c968231c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6d772eaca96731dffcc711e8f1fcff21d997f0f369523dc72c571f8dd97cf601b7180f884e733f31d87e5fbb97c97ed60f93e3fdfdf1f5eb8a5e17d9e0040d344a101000a0010816b789ceddb410a83301005d0809b1ea677cca2d716522c9582a868ab76340f14f10926137f36213eee4dbae5544a77bcce949ad276972ab8bfcf3d277c318e13b603f853bc7c638c31c618638c31c618638c31c618638c31c618638c8fe189ed4b7635e14bb07ce32bb37ce320dc3f7d8b7ce3e03c91d885bcee8780795ef89252f27839a3fc55939bf0bae2ebe0df06365cbe77e1b3e4fbc839bf659501821c27df7f982471fabd2fe721b7731ca7df78c8f22ddf41b9f20c1e3eb03804c7c9c95939ceb7ac9ae30402638c31c618638c31c6cb390f7976597c1dc7a9320ac759c9c11863bc869f3e466469000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013000f810f789cedd23b0a80301404c0401a0fe31d2dbcb6103f68612582c546261016a6dcb7f3585b2b65fb67ecef088c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ee6324c77ae6de988afb838a7581cc1718b7dc73fdf775cdfdd71ce2db17d7fcf39b73488df5f07dbf78d738ac511bc023cd97a4e0100130010811e789cedd2310ac2501045d10f695c8c7b4ce1b685af09361616c1c2bce71918064e35c5bd5d9739c778eeeb6cb31f8c31c618638c31c618638c31c618638c31c618638c31fe1f1e97f59d97793fd583187fc1fac659fca15821e30ad637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637fe351f6b50b1388bf55dcf0f3bb69d7601001300118109789cedd23b0a80400c40c1856d3c8c77b4f0da42fc606321586ee2044260aa146f9d7b446bc7dee79ceb64e5362d4feeb1bdf3387f63fc85f58d73b1627165d637cec58ac59559df38172b1657667de35cac585c99f58d4bb0627165d637c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6ffe11ddb70bac2000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010014000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000019020011000e09789c63000000010001020011000f09789c6300000001000102001100108272789c8d92bf4b033114c7efae3fe295aaad388ae82814b505455c14ece0220eae22e472b94b68ee722439aa9ba548ff00177114fa1f38ab140417ff1047271d7d77d2a120878107f9269f97f723af3a6c95371b752f8d7b54091e32c31c6475eb9f6f5d7bc5cad6f3edc7c1d1c5fbf9e45e7ee507c35669a962a4220c817236c0e6cad9e9fab2929e349c108503c3e3d0604fd01cda022b3b3640c3bd45c3a96a6f1b4a1861549b1c58cb00db9a5976a3a971ec6b23631a614315c7621022cbe54ac69e90a4574256d548b893b0ab05026b96d70025d47daeccd46bc491dd988ae3949e311e18e730e0fc1ae2cca083d322d40d5221fa52faed2ab290a1512268e76617824b1583537605ca8d70186105191647aef63981be43ba8b91d4fa2ac120fd2c9df9ff3f52c99ad419e13f9993f1f805985294fac5af64c48016113029ad859aa11ada9cf01e453027eed3f7ec9c3c3c4eee5e77a673b2dac409bd24383198c79a30cc55fedbfbbfbffd033b26ba6102001100111d789c636cd66116622dc92f4ace60676060603205622d464600335c0357020011001209789c63000000010001020011001309789c63000000010001020011001409789c63000000010001020011001509789c63000000000000000000ac4c4c0000000401000a000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000002e020015000f09789c63000000010001020015001009789c63000000010001020015001109789c63000000010001020015001209789c63000000010001020015001309789c63000000010001020015001409789c63000000010001020015001509789c63000000010001020015001609789c63000000010001020016000009789c63000000010001020016000109789c63000000010001020016000209789c63000000010001020016000309789c63000000010001020016000409789c63000000010001020016000509789c63000000010001020016000609789c63000000010001020016000709789c63000000010001020016000809789c63000000010001020016000909789c63000000010001020016000a09789c63000000010001020016000b09789c63000000010001020016000c09789c63000000010001020016000d09789c63000000010001020016000e09789c63000000010001020016000f09789c63000000010001020016001009789c63000000010001020016001109789c63000000010001020016001209789c63000000010001020016001309789c63000000010001020016001409789c63000000010001020016001509789c63000000010001020017000009789c63000000010001020017000109789c63000000010001020017000209789c6300000001000102001700000000000001494c4c00000003010013001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010009000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000900108179789ceddbdd0a82301806e041275d4cf7e841b71d2c2c4508358d7e5ef30165f0e0c1e7f60edc70e7d3a11c9b526b7bddee520ef5d23618e38e6bbd71697a2e61dcd53d705a0fe28f45b38ce704638c31c618638c31c618638c31c618638c31c618638c31c6781b3cff23ec9f71df074f9ece191d2cdff29d97937d5412c743beefcd04e71c36c839df9093aa9c4ab6ca396193efc5954c9e4f7bdfdc59d7b1f1336da8fbdeec8a73f3bdf6fce50bf95e17e4852cb111fcce8500000000000001504c4c00000005010000001560789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000060789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000160789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000000a04c4c9c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010015000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000b0013810b789cedd23b0a80400c45d181695c8c7bb470db42fc60a39dddc3398110385de0ae73af6aedd8fb9c731d8c31c618638c31c6e3709b9627f7da3e73ce3b183f58df38b42a69e250fe59df39efc473d58b5b18e75495c339f9c4734ec8fac618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c87e21d23a6988601000b001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010001000e60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001000f60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001001060789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010011000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000f000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f0010815a789cedd25b0a82501486d113bd34865e9a4073f4a16907762183a2422be2cfbd04d9b884e3e53bbbedb2ef5b3b9e97713ace03638c7138b75577cbcb7e3f5b1ec6473cfa919b491cf6ab66c3eb369d5b3785c7aedd3d5ee49b7cbf63dfe127ef8d2379b8be6e888631c618638cf11ff2e2f79cf3f118638c31c618638c31c6b3e3e12ec618638c31c618638c31c618638c31c6f835f7f8a79c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef919f2014cb97fb101000f0011817b789cedd2310a02411005d101afe31d0dbcb630ab606866b316560d34032fad7fbf5ef65eeb79efeff5f663ad159fc73b3e9539e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ff977cfb9c218ee33886f38a7fcb3b3e9539e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ef604ef9561500000000000000fa4c4c638c31c618e30f6eca34eafb010001000d60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010014000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010010000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0100100010812b789cedd4510a02211440d11703d11a5a43d012fd985db4d6c06a68181cfa2d9e7604118efe8817e7cb546bc473be97d758168c31c6c9394ea5e5a9de31ee95e316c7864b7c3c8d71c3e7a59bf4bcef7b3d56b66f1d638c31c618e3bfe275f7879ce7f27878d6371e99f58d47667de391396fdf71ddf1e1eb9cee75f0b87d63dc65df18638c31c618638c31c618638c31c6b85fae18638c31c618638c31c618638c31c6382f3f005368bbe10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010001001160789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001001260789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001001360789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000002010014000f8106789cedd6410a80201005d001371da63bb6e8dac15462b869978b9027c81f1e6e842fb8af2533e2da2dee5503638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3578e65ab438b889247e77e7a20ffe7f2787ad66f8c87b2d7806766fdc6f8613f253c33eb37fec0275835b7d40100140010811a789cedd93b0a80400c40c1051b0fe31d2dbcb6b07eb05150d4cac459580253a5785d86aea9b594f96f6379ebf80797b6df7353c773fecede18df617de358fcac587de358ac6f1c8dfb238f57fc9dbd31d637cec78ac59959df38162b1667667de358ac589c99f58d13f0e92d43df3801bbec618c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ec3130184cc4400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000601000f000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000cb4c4c0000000401001c000d60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001c000e60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001c000f60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001c001060789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000029020012000e09789c63000000010001020012000f09789c6300000001000102001200101d789c636cd66116622dc92f4ace60676060607204624e1646003353034502001200111d789c636cd66116622dc92f4ace6067606060f205620346460034160375020012001209789c63000000010001020012001309789c63000000010001020012001409789c63000000010001020012001509789c63000000010001020012001609789c63000000010001020012001709789c63000000010001020012001809789c63000000010001020013000009789c63000000010001020013000109789c63000000010001020013000209789c63000000010001020013000309789c63000000010001020013000409789c63000000010001020013000509789c63000000010001020013000609789c63000000010001020013000709789c63000000010001020013000809789c63000000010001020013000909789c63000000010001020013000a09789c63000000010001020013000b09789c63000000010001020013000c09789c63000000010001020013000d09789c63000000010001020013000e09789c63000000010001020013000f09789c63000000010001020013001028789c636ed66116622dc92f4ace60676060604a076206464634d134aca2f9402cc7c800007bb30a3f0200130011097800000000000001264c4c00000006010010000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000f3464600000000000000000000002f000000000000002600000000000000c300000000000000b200000000000000cf000000000000008b000000000000002c0000000000000032000000000000011b000000000000004700000000000000ff000000000000013c0000000000000178000000000000013d000000000000016700000000000000fa000000000000008600000000000000b5000000000000011c00000000000000b7000000000000000800000000000000f2000000000000018c000000000000012100000000000000e7000000000000014b000000000000003c000000000000016600000000000001590000000000000103000000000000011a0000000000000037000000000000018e00000000000001940000000000000192000000000000003400000000000000d5000000000000013a00000000000001890000000000000085000000000000011000000000000000c600000000000000c500000000000000f3000000000000008f00000000000000ab00000000000001650000000000000182638c31c618638c31c618638c31c618638c3fb8015324dafc010015001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000fc4c4c31c618638c3fb8015324dafc010008000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c09789c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000601001a000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000017d4c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010010000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000174c4c00000006010006000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000000b4c4c00000006010010000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000984c4c31c618638c3fb8015324dafc010010000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4cc1c9dcf2fb79df17e3d158df18efe3963f9918e074305eb0bef101d8440427b3be31c6f8887c03208fb5f00100070011814b789cedd74b0ac2401444d140262ec63d66e0b685f6831385d0061b7d564e401ace28e82d624ec7b9b569ba7e1ec7edba1f18638c31c618638c31c618e3249e0ecb33cfed5cea0631fe80f58d9359df3899f58d9359df3899f58dbf56551daef355e13fe43a21eb1b8f67b1e164d6374e667de364d6374ee63a2f92ab935a5eefdbd2f0bb5c27e4ad8f8c95ecb771959f01c7f34ffe1219094eee7b081b094eee7b081b4938efbcef216c241877d84830eeb09160dc6123c1b8c3468271878d04e30ecb1eef8e2fc56ea71a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000007010007001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010008000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000009c4c4c31c618638c3fb8015324dafc010008000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010005001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010006000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000a24c4c00000003010013001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000002010000000c60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000000d60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010004001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010006000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000801000d001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01000d001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901000e000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001074c4c0000000301001100108158789cedd6510a82401440d101215a436b688ff3d12e5a6b3095264208256a3ea723887a141cf52a5ece4d29293de6d7e239b50b8c31c6c1391d73bb724d876ebb29b78187a331de259fbab0dffbce69f4e845b83b25de98d77cc46182e8b7f3f059c718638c318ec0fddeef38ceb831d637fe77d637ae99f58d6b667de39a59dfb866d6f7dc7bb2578e73bf3d4b8c3ff0b4bebd0d786b5ef3fbad6fbc35fb3fc1788c4b9891603ca3d8691ce77270f5bc48b1fac63517ab6f5c73b1fac63fe33821638c31c618638c31c618638c31c618e3fdf11d15eba22901001100118117789cedd44b0a8020140550c149bb7003edb141db0eaca468d6c71a241c419e9ec11d5d1dfb987308cbdec6bacac018638c31c618638c31c618638c9be6d00de5d0a5ed1ef374c947086e815393acdf58bfeff151e4f07936c635fcec159f67eb37fe1beb37c63b9fd75ebf71db5cf5ad638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638cdff00c7b916878010011001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010004000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000601000e001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901000f000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001064c4c00000002010014000f8106789cedd6410a80201005d001371da63bb6e8dac15462b869978b9027c81f1e6e842fb8af2533e2da2dee5503638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3578e65ab438b889247e77e7a20ffe7f2787ad66f8c87b2d7806766fdc6f8613f253c33eb37fec0275835b7d40100140010811a789cedd93b0a80400c40c1051b0fe31d2dbcb6b07eb05150d4cac459580253a5785d86aea9b594f96f6379ebf80797b6df7353c773fecede18df617de358fcac587de358ac6f1c8dfb238f57fc9dbd31d637cec78ac59959df38162b1667667de358ac589c99f58d13f0e92d43df3801bbec618c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ec3130184cc4400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000002e020003001309789c63000000010001020003001409789c63000000010001020003001509789c63000000010001020003001609789c63000000010001020004000009789c63000000010001020004000109789c63000000010001020004000209789c63000000010001020004000309789c63000000010001020004000409789c63000000010001020004000509789c63000000010001020004000609789c63000000010001020004000709789c63000000010001020004000809789c63000000010001020004000909789c63000000010001020004000a09789c63000000010001020004000b09789c63000000010001020004000c09789c63000000010001020004000d09789c63000000010001020004000e09789c63000000010001020004000f09789c63000000010001020004001009789c63000000010001020004001109789c63000000010001020004001209789c63000000010001020004001309789c63000000010001020004001409789c63000000010001020004001509789c63000000010001020004001609789c63000000010001020005000009789c63000000010001020005000109789c63000000010001020005000209789c63000000010001020005000309789c63000000010001020005000409789c63000000010001020005000509789c6300000001000102000500000000000001394c4c18638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000009010004001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010004001860789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010005000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000012b4c4c00000003010013000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000900138101789cedd23b0a80400c05c0c0361ec63b5a786d217eb0b1105658615926101e4c95c05be7921971ec1de75c81717b8e697972c9ed9dfbb91be31ad66f3c327feb7713eee7793c3ceb37c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c7fe01d902fc67a010009001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000509789c63000000010001020019000609789c63000000010001020019000709789c63000000010001020019000809789c63000000010001020019000909789c63000000010001020019000a09789c63000000010001020019000b09789c63000000010001020019000c09789c63000000010001020019000d09789c63000000010001020019000e09789c63000000010001020019000f09789c63000000010001020019001009789c63000000010001020019001109789c63000000010001020019001209789c63000000010001020019001309789c63000000010001020019001409789c63000000010001020019001509789c6300000001000102001a000009789c6300000001000102001a000109789c6300000001000102001a000209789c6300000001000102001a000309789c6300000001000102001a000409789c6300000001000102001a000509789c6300000001000102001a000609789c6300000001000102001a000709789c6300000001000102001a000809789c6300000001000102001a000909789c6300000001000102001a000a09789c6300000001000102001a000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000601000a001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01000a001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901000b000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000334c4c00000006010015000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000824c4c00000032020001000f09789c63000000010001020001001009789c63000000010001020001001109789c63000000010001020001001209789c63000000010001020001001309789c63000000010001020001001409789c63000000010001020001001509789c63000000010001020001001609789c63000000010001020002000009789c63000000010001020002000109789c63000000010001020002000209789c63000000010001020002000309789c63000000010001020002000409789c63000000010001020002000509789c63000000010001020002000609789c63000000010001020002000709789c63000000010001020002000809789c63000000010001020002000909789c63000000010001020002000a09789c63000000010001020002000b09789c63000000010001020002000c09789c63000000010001020002000d09789c63000000010001020002000e09789c63000000010001020002000f09789c63000000010001020002001009789c63000000010001020002001109789c63000000010001020002001209789c63000000010001020002001309789c63000000010001020002001409789c63000000010001020002001509789c63000000010001020002001609789c63000000010001020003000009789c63000000010001020003000109789c6300000001000102000300000000000000ee4c4c0000000401000d001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000023020014000509789c63000000010001020014000609789c63000000010001020014000709789c63000000010001020014000809789c63000000010001020014000909789c63000000010001020014000a09789c63000000010001020014000b09789c63000000010001020014000c09789c63000000010001020014000d09789c63000000010001020014000e09789c63000000010001020014000f09789c6300000001000102001400101d789c636cd66116622dc92f4ace60676060606a076206464600351c037f020014001109789c63000000010001020014001209789c63000000010001020014001309789c63000000010001020014001409789c63000000010001020014001509789c63000000010001020014001609789c63000000010001020014001709789c63000000010001020014001809789c63000000010001020015000009789c63000000010001020015000109789c63000000010001020015000209789c63000000010001020015000309789c63000000010001020015000409789c63000000010001020015000509789c63000000010001020015000609789c63000000010001020015000709789c63000000010001020015000809789c63000000010001020015000909789c63000000010001020015000a09789c63000000010001020015000b09789c630000000100000000000000c34c4c00000009010002001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010003000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c0000000000000101494900000000120000000000000041010009000500000000000000e5010009000d000000000000007f010009001300000000000000ac0100090017000000000000000201000a0004000000000000005901000a000b000000000000016801000a000f000000000000016c01000a0011000000000000016401000a0014000000000000002301000a001800000000000000ae01000b0004000000000000013701000b000c000000000000009401000b000f000000000000019401000b0013000000000000002c01000b0017000000000000006001000c0005000000000000013e01000c000b00000000000000b701000c000f000000000000018900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c0000000401000f000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000003002000c000e09789c6300000001000102000c000f1d789c636cd66116622dc92f4ace6067606060ec06e25f8c8c00381a047b02000c001009789c6300000001000102000c001109789c6300000001000102000c00121f789c636cd66116622dc92f4ace6067606060ec616060f262640000361403cc02000c00131f789c636cd66116622dc92f4ace6067606060ec6360604a61640400367103e902000c001409789c6300000001000102000c001509789c6300000001000102000c001609789c6300000001000102000c001709789c6300000001000102000c001809789c6300000001000102000d000009789c6300000001000102000d000109789c6300000001000102000d000209789c6300000001000102000d000309789c6300000001000102000d000409789c6300000001000102000d000509789c6300000001000102000d000609789c6300000001000102000d000709789c6300000001000102000d000809789c6300000001000102000d000909789c6300000001000102000d000a09789c6300000001000102000d000b09789c6300000001000102000d000c09789c6300000001000102000d000d09789c6300000001000102000d000e09789c6300000001000102000d000f09789c6300000001000102000d00101f789c636cd66116622dc92f4ace60676060605cc3c0c0c4000000000000015d4c4c0000003002000c000e09789c6300000001000102000c000f1d789c636cd66116622dc92f4ace6067606060ec06e25f8c8c00381a047b02000c001009789c6300000001000102000c001109789c6300000001000102000c00121f789c636cd66116622dc92f4ace6067606060ec616060f262640000361403cc02000c00131f789c636cd66116622dc92f4ace6067606060ec6360604a61640400367103e902000c001409789c6300000001000102000c001509789c6300000001000102000c001609789c6300000001000102000c001709789c6300000001000102000c001809789c6300000001000102000d000009789c6300000001000102000d000109789c6300000001000102000d000209789c6300000001000102000d000309789c6300000001000102000d000409789c6300000001000102000d000509789c6300000001000102000d000609789c6300000001000102000d000709789c6300000001000102000d000809789c6300000001000102000d000909789c6300000001000102000d000a09789c6300000001000102000d000b09789c6300000001000102000d000c09789c6300000001000102000d000d09789c6300000001000102000d000e09789c6300000001000102000d000f09789c6300000001000102000d00101f789c636cd66116622dc92f4ace60676060605cc3c0c0c4000000000000011c4c4c00000003010012000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000f73789cedd2310a80301004c083343e267fb4c8b7854b2236e91502cec2b130ed6dab253362dc533377618c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f85b8ee35cb9e4f51bdee70dd8bedfe70e9caabac201001200108159789cedd84d0a83301446d18050ba86aea17b74d06d17d21f1cb4410a81809ff508229c81a8ef46c4db75aab594e7be1c5edbfb90c3e53c7ff354efb887736689f53d9e7366299fb5e9cced75ffe494078b23b85cca692db63e9e9b730fe495ebeee3ace78d37e125aeb693bdf2e75d5a0d3828cdccd5103934acef4d1649e4880fcd399dec95736689f5adef63714e27f19c3334ac6f21e3a8aa848cc7734e6cfe68e3f19c13b2772c1ecf8ac5ffccc3bf0a848c43599a18638c31c618638c31c618638c31c618638c31c618638c31c618631cc80f310beafd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000b000960789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01000b000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010015001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010015001860789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010015001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010016000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000f44c4c00000006010011000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001054c4c31c618638c3fb8015324dafc01000c000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010003000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010013000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010009000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000a000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000a000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000f000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000301000700128109789cedd2310a80301045c180d7f18e165e5b484cb0122cec3ec92c8485a9b2f0ce7dabb594fb3dabcf5818638c31c618638c31c618638c31c618638c31c618638c31c618a7f3f1e62bec837855fe48f31fe79c83e76169e25096260e6569e25096260e6569e25096260e6569e25096260e6569e229589a18638c31c618638c31c618afca0dcc1dea7c010007001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0001020015000c09789c63000000010001020015000d09789c63000000010001020015000e09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000002e020015000f09789c63000000010001020015001009789c63000000010001020015001109789c63000000010001020015001209789c63000000010001020015001309789c63000000010001020015001409789c63000000010001020015001509789c63000000010001020015001609789c63000000010001020016000009789c63000000010001020016000109789c63000000010001020016000209789c63000000010001020016000309789c63000000010001020016000409789c63000000010001020016000509789c63000000010001020016000609789c63000000010001020016000709789c63000000010001020016000809789c63000000010001020016000909789c63000000010001020016000a09789c63000000010001020016000b09789c63000000010001020016000c09789c63000000010001020016000d09789c63000000010001020016000e09789c63000000010001020016000f09789c63000000010001020016001009789c63000000010001020016001109789c63000000010001020016001209789c63000000010001020016001309789c63000000010001020016001409789c63000000010001020016001509789c63000000010001020017000009789c63000000010001020017000109789c63000000010001020017000209789c63000000010001020017000000000000017c4c4c0000000102001000108660789cd555cd6ed3401076feea346d43698b2a81387002210eb482130815a14a484808892312626c4fec25fb6376d76dc285fe407be335780d5e8137a0cfc00b309bd821719dc0154b2b79f79b999d9f6f66bba7f71a67afba90e2c0242ce52aeca3f63dcfab6fd25aa979335f6daf7da006c877eef7cf99effd371b5f63642c137f51097886855867889cabc389d634d69620d5a186d46d96638d280b68faa659a46c70da4627d320592694c68aed8ce822bd09b6b14869c5280e7aee6d1dc785310fdae5eb220642c92897f463c58bffb2d14bfb94836572b25fa43b8395f59856b2ea7f4a67deffdf7c2c85b79af2ccaa3c33fea53c79b5f98b9aead656a2388b60186ae85104b18580e3a8b3966835eb3512daee58341c4ccafa63a8e3a096d3dff21318a62c5769d25aab79552acb13954b507b027d0ebb6142fc1518c10103b93bc2b71d5e6ef1f56eace100b9008b9a01ff404416100bd0c4892f995f5b2f90e719be4e58cfd6f77a8c1d916ed3808cde50e622a66d21f57491c68ce466a5a43e3f77925da122d4d2d1a1a7b438b943b5359072caecc90bbfd93616c54b10d8a2ae03632cb5deaa3bfb6368fdd7cd3d32b4d2a3ba408c23e1515b07d49857f2d389f8519e8faed52c005edcfbdcf75a870982ad97c27c52e9fc077fe47ccb2566f76c7f512a8a688e00000000000000c64c4c1f4f47b3643813389c0de5fbed6f5fdf954359eae94ca4c34b817c7ffbe8c7bb72aa4fee56bab27f71f1d3d94de023e8c8d2244888f85b2118cb31615184d2d22c8894d214ff0ab189fa41a005ee3a8278761254f1ec7a25cfd6834cd2900990ac3fa3e20e1ad46331f1d7a42091b7c6ad4475a7118a7a3c076272a79b0cb9b29c83a463b9738bf849f381deaecc24ce2bc5261849afe56d485da1995d23f5fc5aa5fa141736493d75f201460f48bd6315e54519c4883cd84832e9ae8db5ca6464950edd15abc573e912b151220265624195374315d01c303458b0103abdfacf2d72fc699ce61b5569be5999669f122c6080ceef71e89cc5894d3a538f5af3cfc34562553e8edeb350a5296a9a7fa77ddfbb7aa894e303f022dd94ed25f2a8cf5c736c3872e001f0512b5a0e22a5d32967fc5001275bc70fa75fca464e2ba7491571dee4254833f99e9148d837bb74dc1eb9972867aa1380a07aba6af87ee524accf1f928df9d0b5f9506d3eb435867e030386c417000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000007010006000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000015149490000000013000000000000003d01001e00050000000000000031020001000f00000000000000b0020003001300000000000000a802000500130000000000000009020007001100000000000000400200090007000000000000002b02000a000d000000000000003a02000c000e00000000000000b602000e000c000000000000015202000f000b00000000000000d002000f001600000000000000dc0200100010000000000000016402001000110000000000000158020011000e0000000000000148020012000e000000000000016f02001400050000000000000196020015000f000000000000007d0200170010000000000000010202001a000c000000000000004e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049490000000016000000000000002101000000080000000000000109010000000900000000000000da010000000c000000000000009f010000000e00000000000000f5010000001100000000000000380100000015000000000000008001000100020000000000000115010001000800000000000000d8010001000e00000000000000840100010011000000000000008a01000100140000000000000074010001001700000000000000f90100020003000000000000005101000200090000000000000015010002000f000000000000005c01000200120000000000000062010002001600000000000000b301000300070000000000000124010003000d00000000000000bd010003001000000000000000eb0100030016000000000000002501000400040000000000000138000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c638c31c618e30f6eca34eafb01001c000c60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000f000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000601001b000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b001060789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61800000000000000614c4c31c618638c3fb8015324dafc010003001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c1d42d6377e19eb1bef9973fa963daee79c90658feb39a758d9e37ace491347704e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9acbf90462c5a64600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010014001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000b02000f000b09789c6300000001000102000f000c09789c6300000001000102000f000d09789c6300000001000102000f000e09789c6300000001000102000f000f09789c6300000001000102000f00108107789c636bd66196e0cec84fce4ead2c494cca496567606060fcc2c0c0c4c2c8009413e34c2c48ad28c84ccccb07cbfc02c930310265a478934af3b2538b0af28b4b528b8cc0b21f81b29c607d12dc498929e9f9f90539a5c51960b99770336505406616a526e717a514e42456a6168115fc871b2dc45a925f940cd1f61328cac5c2000013d4264702000f001109789c6300000001000102000f001209789c6300000001000102000f001309789c6300000001000102000f001409789c6300000001000102000f001509789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010011001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010011001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010012000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000005010013001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010013001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000000764c4c00000006010019000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000e44c4c0000000401000c000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000c000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4ce2d2ebdf1308813325f00d77c9fa98f6bdb5d7fe1cef751c3fe1a5e7ed02d7790ece6169e2a22c4d8c31c618638c31c618638c31c618638c31c618638c31c618638c31c6189f78e9f9ca678331aef3781ccffac6c92c4d9cccfac6c9ac6f9ccb6dee429e8e90bf709d7be37fe5b162f58defc6631387f904df8b158b9359df3899f58d9359df3899f58d93b978df4f901de60e01000c00128139789cedda410a83301040d1809b1ec63bbae8b50bb196bae8428818613a798204de2a307f7679ce53ada5bcffefb17d9f03e3162e8fe597a7fa3ae638f7c6b885f58dff8b158b33b3be7166d637ceccfa1e95cf4d7e0c8e331daceffe1c673a6639ea2cb1be5b38ce74f0d590e35c10e30bac6f8c31c618638c31c618638c31c618638c31c6f87e8ef37cc98b29dc9fe3c4a66f8cbbb26dc09959df18ef6c1b7066d637ceccfac69959df18ef6c1b7066d677085e019f82488000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401001b001260789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001b001360789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001b001460789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001b001560789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010001000860789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000960789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001000a60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001000b60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010001000c60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61800000000000000874c4c00000009010012000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000f84c4c00000003010000000960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000000a60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000000b60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000f000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000001302000f001609789c6300000001000102000f001709789c6300000001000102000f001809789c63000000010001020010000009789c63000000010001020010000109789c63000000010001020010000209789c63000000010001020010000309789c63000000010001020010000409789c63000000010001020010000509789c63000000010001020010000609789c63000000010001020010000709789c63000000010001020010000809789c63000000010001020010000909789c63000000010001020010000a09789c63000000010001020010000b09789c63000000010001020010000c09789c63000000010001020010000d09789c63000000010001020010000e09789c63000000010001020010000f09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010002000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000021d0000020d070000021e0000020d070000021f0000020d07000002200000020d07000002210000020d07000002220000020d07000002230000020d07000002240000020d07000002250000020d07000002260000020d07000002270000020d07000002280000020d07000002290000020d070000022a0000020d070000022b0000020d070000022c0000020d070000022d0000020d070000022e0000020d070000022f0000020d07000002300000020d07000002310000020d070000020a0000020c07000002300000020c07000002310000020c070000020a0000020b07000002300000020b07000002310000020b070000020a0000020a07000002300000020a07000002310000020a070000020a000002090700000230000002090700000231000002090700000232000002090a00000233000002090a00000234000002090a00000235000002090a00000236000002090a00000237000002090a00000238000002090a00000239000002090a0000020a00000208070000023a000002080a0000023b000002080a0000020a00000207070000023c000002070a0000023d000002070a0000020a00000206070000023e000002060a0000023f000002060a0000020a00000205070000023f000002050a0000020a00000204070000023f000002040a0000020a00000203070000020b00000200000000000001204c4ccf336783ed3b9e67ce06db773ccf9c0db6ef789e391b6cdff13c7336d8bee379e66cb07dc7f3ccd960fb8ee799b3c1f61dcf336783ed3b9e67ce06db773ccf9c0db6ef789e391b6cdff13c7336d8bee32ff900557af55801000f0012811d789cedd2d10983501044d105db4997b62dbc2858c2480673168685f37df7cfb6d6ccb9fb5db78e99793f2ffca7dcd3a0be719e7b1ad437ce734f83fac679ee6950df38cf3d0dea1be7b9a7417de33cf734a86f9ce79e06f58df3dcd3a0be719e7b1ad437ce734f83d2c47916327e333f99a6bef1af59df18638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61887f80bb4dbd96d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010016000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000701001c000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000012a4c4c31c618638c3fb8015324dafc01001b000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010009000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010019000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000008010009000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000bf4c4cc2795b07d498178bd3a9f861c147cf6a16002fef7dec7bed5182609b9530bfa975feb99f3bdf76c4ec9d3e5a464519cdd1bdd968560d6702c7f3a1bcb9fedbeb67d55056fb3a13e9f85c206f7ebcfbd7b32ad5c7376a5d79f4f6ed3fce6e022f40479626414285bf1b82b11c131645282dcd8248294df1af5135513f08b4c05d47509d1d077575f6456d9d6d0699a4211320597f40c93d58a11e8ba97e4d0a12797bd24a94771aa1a827732026777ac9982bcb39483a96b7ae517dd27ca0b72b3389f34ab12946d21b451b525768663748bdb856a901c5852d524f9d7c80d16d52ef5a45bc2883189107db4926ddb5b156998cacd2a1bb62bd7c2e1d11db95422026966479275401cd014383054ba193adcf6e91a39f27345fa9a3f96a2dcd3e112ce0009ddf93d0398b139b74671eb5d6c7878bc4ea7cccdfb350a5296a9a7f2703dfdb1a29e5ea81fe66147413dbabe4d180b9e6d876c58143e0792b5a0e22a5d31967fc5001275b4777665fca95a2ac9c2665c47953a420cde44f8c44c281d9a3e34eee5ea29ca96e0082f2e9b2e1fbb593b0b97848ae2c862e2d861a8ba1dd09f40189a3d1ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000019020011000e09789c63000000010001020011000f09789c6300000001000102001100108273789c8d52cd4ac34010dea43f6b4ab53fe84110d1a350fce941c48b057bf0221e7c00d96c36c9d24d36ec6ea8de2c45fa00be82c5b750a117f14d3c7a103c787012e9a120c181819d996ffef69beab853eeacd40cd382e8840f18c6a8ef3c7df5ad0d94c9f3fdfbc9e9fadaf7acf579953bc69dd2f8a861385307fb86d190864c1b0c017b0bb46ca105b19a2d4d624f1b19b38818a63811a30023872b19bb42d24109a3aa911093f0aaf930452878101a1ba3bac79599674d38b69a73e32c659721f78dddf339bf853e0bd0d14511d4f1532186527a07558cb061512258f7ee109a4b1543521602cb8948101105131677ae0e391d3005e33622a9f54d42c0f4b27196ff5fa4927d527742fec49c4fa72f802945a9575c25438c581102c8db5e55d2958653aa886f781c18e20a9613b89711685b7011bbcdba9bc6b0564e4508cbf5eb1faf8b37d17b98b5df1ee737b1d92209bba6243184c79a8684abbce6f1ef5100a25d3152d130f7ee802e95d10fec8cb8a502001100111d789c636cd66116622dc92f4ace60676060603205622d464600335c0357020011001209789c63000000010001020011001309789c63000000010001020011001409789c63000000010001020011001509789c630000000000000001214c4c0000001302000f001609789c6300000001000102000f001709789c6300000001000102000f001809789c63000000010001020010000009789c63000000010001020010000109789c63000000010001020010000209789c63000000010001020010000309789c63000000010001020010000409789c63000000010001020010000509789c63000000010001020010000609789c63000000010001020010000709789c63000000010001020010000809789c63000000010001020010000909789c63000000010001020010000a09789c63000000010001020010000b09789c63000000010001020010000c09789c63000000010001020010000d09789c63000000010001020010000e09789c63000000010001020010000f09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f9010015000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000d00108169789cedd5db0a82401405d0015ffa98fe711efaedc02e68505034ead471660921adc0ced96ef1741cc631a5eb673add8efb09638c71704e87fcccc378c638e5128e33771c2e4b50b0bfad669c8bace3f9fbe32f13c66f5fff7106c418638c31c618638c31c618638cbbe65cc471e6c678fbc6963d0d1e121ca255f3af932ce338ebe076aa59d6d89afd5e5bfbb26be7575e1c6ccde523f3a704bfe638ebe0766ef15ee7fe43267106dc2b6f52b6aeabb949b071e6de2bd7ac661fb5ef634bc1b6b3656309f671d3ba66c1568a4a825835312e61d5c418638c31c618638c31c61863dc1e5f00b36d4a5e01000d00117d789cedce310a80300c05d040170fe31d3b786d216a2d8882e0e020f802e193970c99c69219b1768fad5a608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c5fe018ea994bce6d57afd7dfe29bbf31c6f837dce783f7c018638c31c618638c31c618638c31c618638c31c6f8112fcba18ae10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010003001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000cd4c4c0000001802000e000c09789c6300000001000102000e000d09789c6300000001000102000e000e09789c6300000001000102000e000f09789c6300000001000102000e001024789c636ad66116622dc92f4ace6067606060bcc8c0c0c4c2c888267a00220a00c15c078602000e00111f789c636cd66116622dc92f4ace60676060603cc3c0c064c0c80000378603f202000e001209789c6300000001000102000e001309789c6300000001000102000e001409789c6300000001000102000e001509789c6300000001000102000e001609789c6300000001000102000e001709789c6300000001000102000e001809789c6300000001000102000f000039789c636cd661d113e0292ec9cf4b4d2b2dca4b4c4e65626770fe70dbc73ee2b78cf952f76d87e6868a3bb76aef38c4b62a90010400bd87112f02000f000109789c6300000001000102000f000209789c6300000001000102000f000309789c6300000001000102000f000409789c6300000001000102000f000509789c6300000001000102000f000609789c6300000001000102000f000709789c6300000001000102000f000809789c6300000001000102000f000909789c6300000001000102000f000a09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c9c6300000001000102000a000b09789c6300000001000102000a000c09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000209789c63000000010001020003000309789c63000000010001020003000409789c63000000010001020003000509789c63000000010001020003000609789c63000000010001020003000709789c63000000010001020003000809789c63000000010001020003000909789c63000000010001020003000a09789c63000000010001020003000b09789c63000000010001020003000c09789c63000000010001020003000d09789c63000000010001020003000e09789c63000000010001020003000f09789c63000000010001020003001009789c63000000010001020003001109789c63000000010001020003001209789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000d000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010011000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001174c4c00000008010006001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010007000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000005b4c4c0000001302000f001609789c6300000001000102000f001709789c6300000001000102000f001809789c63000000010001020010000009789c63000000010001020010000109789c63000000010001020010000209789c63000000010001020010000309789c63000000010001020010000409789c63000000010001020010000509789c63000000010001020010000609789c63000000010001020010000709789c63000000010001020010000809789c63000000010001020010000909789c63000000010001020010000a09789c63000000010001020010000b09789c63000000010001020010000c09789c63000000010001020010000d09789c63000000010001020010000e09789c63000000010001020010000f09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010010000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010016000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010000000e60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000000f60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010000001060789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff494900000000120000000000000041010009000500000000000000e5010009000d0000000000000157010009001300000000000000ac0100090017000000000000000201000a0004000000000000005901000a000b000000000000001001000a000f000000000000000d01000a0011000000000000001201000a0014000000000000002301000a001800000000000000ae01000b0004000000000000013701000b000c000000000000004201000b000f000000000000004501000b001300000000000000fe01000b0017000000000000006001000c0005000000000000013e01000c000b00000000000000d401000c000f000000000000016300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c0000000601001b000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001b000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000e24c4c31c618638c3fb8015324dafc010012000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010001001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010002000060789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000160789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010002000260789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4ccf336783ed3b9e67ce06db773ccf9c0db6ef789e391b6cdff13c7336d8bee379e66cb07dc7f3ccd960fb8ee799b3c1f61dcf336783ed3b9e67ce06db773ccf9c0db6ef789e391b6cdff13c7336d8bee32ff900557af55801000f0012811d789cedd2d10983501044d105db4997b62dbc2858c2480673168685f37df7cfb6d6ccb9fb5db78e99793f2ffca7dcd3a0be719e7b1ad437ce734f83fac679ee6950df38cf3d0dea1be7b9a7417de33cf734a86f9ce79e06f58df3dcd3a0be719e7b1ad437ce734f83d2c47916327e333f99a6bef1af59df18638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61887f80bb4dbd96d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010012000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010015001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010015001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000b0013810b789cedd23b0a80400c45d181695c8c7bb470db42fc60a39dddc3398110385de0ae73af6aedd8fb9c731d8c31c618638c31c6e3709b9627f7da3e73ce3b183f58df38b42a69e250fe59df39efc473d58b5b18e75495c339f9c4734ec8fac618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c87e21d23a6988601000b001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000001802000e000c09789c6300000001000102000e000d09789c6300000001000102000e000e09789c6300000001000102000e000f09789c6300000001000102000e001024789c636ad66116622dc92f4ace6067606060bcc8c0c0c4c2c888267a00220a00c15c078602000e00111f789c636cd66116622dc92f4ace60676060603cc3c0c064c0c80000378603f202000e001209789c6300000001000102000e001309789c6300000001000102000e001409789c6300000001000102000e001509789c6300000001000102000e001609789c6300000001000102000e001709789c6300000001000102000e001809789c6300000001000102000f000039789c636cd661d113e0292ec9cf4b4d2b2dca4b4c4e65626770fe70dbc73ee2b78cf952f76d87e6868a3bb76aef38c4b62a90010400bd87112f02000f000109789c6300000001000102000f000209789c6300000001000102000f000309789c6300000001000102000f000409789c6300000001000102000f000509789c6300000001000102000f000609789c6300000001000102000f000709789c6300000001000102000f000809789c6300000001000102000f000909789c6300000001000102000f000a09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000009010019001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001a000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001774c4c31c618638c3fb8015324dafc010003000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000003e020017001009789c63000000010001020017001109789c63000000010001020017001209789c63000000010001020017001309789c63000000010001020017001409789c63000000010001020017001509789c63000000010001020018000009789c63000000010001020018000109789c63000000010001020018000209789c63000000010001020018000309789c63000000010001020018000409789c63000000010001020018000509789c63000000010001020018000609789c63000000010001020018000709789c63000000010001020018000809789c63000000010001020018000909789c63000000010001020018000a09789c63000000010001020018000b09789c63000000010001020018000c09789c63000000010001020018000d09789c63000000010001020018000e09789c63000000010001020018000f09789c63000000010001020018001009789c63000000010001020018001109789c63000000010001020018001209789c63000000010001020018001309789c63000000010001020018001409789c63000000010001020018001509789c63000000010001020019000009789c63000000010001020019000109789c63000000010001020019000209789c63000000010001020019000309789c63000000010001020019000409789c6300000001000102001900000000000000ad4c4c000000040100100011811f789cedd4410a83301040d1816c728b5ec03b76d16b0ba94aa14410845619f40542e09145203f790da5b588697e96792c0bc618638c31c618638c31c618638cefc1519f3d9736e2641cf5d1719e7cd273babbc47bfa5eed0ebcc9595e1adee46fdff9f2398efff243a4bb4bbca7ef6407c4f807d637be32eb1b638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3f3f80d0f509efb010010001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c1d42d6377e19eb1bef9973fa963daee79c90658feb39a758d9e37ace491347704e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9acbf90462c5a64600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010011000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000f000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000e000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401001d000c60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001d000d60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001d000e60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001d000f60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000001010000000860789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010016000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001474c4c0000000401000f000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f0010815a789cedd25b0a82501486d113bd34865e9a4073f4a16907762183a2422be2cfbd04d9b884e3e53bbbedb2ef5b3b9e97713ace03638c7138b75577cbcb7e3f5b1ec6473cfa919b491cf6ab66c3eb369d5b3785c7aedd3d5ee49b7cbf63dfe127ef8d2379b8be6e888631c618638cf11ff2e2f79cf3f118638c31c618638c31c6b3e3e12ec618638c31c618638c31c618638c31c6f835f7f8a79c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef919f2014cb97fb101000f0011817b789cedd2310a02411005d101afe31d0dbcb630ab606866b316560d34032fad7fbf5ef65eeb79efeff5f663ad159fc73b3e9539e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ff977cfb9c218ee33886f38a7fcb3b3e9539e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ef604ef9561500000000000000df4c4c0000000601001c000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000a60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001c000b60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61800000000000000ca4c4c638c31c618e30f6eca34eafb01001d000160789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000260789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000360789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000601000d000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000003b4c4c020c070000022c0000020c070000022d0000020c070000022e0000020c070000022f0000020c070000020b0000020b070000020c0000020b070000020d0000020b070000020e0000020b070000020f0000020b07000002100000020b07000002110000020b811b000002120000020b07000002130000020b07000002140000020b811b000002150000020b07000002160000020b07000002170000020b07000002180000020b07000002190000020b070000021a0000020b070000021b0000020b811b0000021c0000020b070000021d0000020b070000021e0000020b070000021f0000020b07000002200000020b07000002210000020b07000002220000020b811b000002230000020b07000002240000020b07000002250000020b07000002260000020b07000002270000020b07000002280000020b07000002290000020b811b0000022a0000020b070000022b0000020b070000022c0000020b070000022d0000020b070000022e0000020b070000022f0000020b070000020b0000020a070000020c0000020a070000020d0000020a070000020e0000020a070000020f0000020a07000002100000020a07000002110000020a811b000002120000020a07000002130000020a07000002140000020a811b000002150000020a07000002160000020a07000002170000020a07000002180000000000000000002d4c4c000000040100120011810e789cedd23d0a80300c06d042170fe31d1dbcb6507f7071108a421be51542e02d4dd36f1e7329296d75b6fd1c0d638c31c618638c31c618638c31c618638c31c64f380dd3957359420d88f10bbec9f7cf38cebe71db0c76b852be71b3b0c579e557378865b037c7f94b2cdf18638c31c618638c31c618638c31c618638c31c618638c31c618638cab790549ac7d3c010012001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010018000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000002f4c4c00000006010004000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000a54c4c31c618638c3fb8015324dafc010004000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010003000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010001000260789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000360789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000460789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000560789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010001000660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000000204c4c638c31c618e30f6eca34eafb01001d000960789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000a60789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb01001d000b60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010011000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010005000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000e0011817e789ceddacb0a8250184561c1490fd33b36e8b503bb100e2288533b5b6d962007be91fe2c8e0a1ef7f3b24cd3e5bc2fd7e3b6c8f2caa72ee60c564630274dfb96f3cc49d3bee53c73d2b46f39cf9c34ed5bce33274dfb96f3cc49d3bee53c73d2b46f39cf9c34ed5bce33274dfb963fe6c3f34e36e769f7c0f31b4c1aac8c604adf21e60c16ce91fd6474f7210451c6acaa386cdf1dccaa8a532ce7ba37664e9af66ddf79e6a459d8f7771fff94bb4433274dfbb6ef3c73d21ce71f7c34d9a09c65fb969bf99fdf4f64f915dbb7dcccf62d37b37dcbcd6cdf7233dbb7dcccf62d37b37dcbcd6cdf7233dbb75cc185ff57c9f2caf62d37f378df671919abea01000e00127e789cedd2310ac020104541c1ebe4965e5b301ad2a44f21df11d685e9165ebbea18a5cc79d77acfc27843ee7ff03ee760fc617de30359df3899f58d9359df3899f58d9359df3899f58d9359df3899f58d9359df18638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3f9ddf90fdab401000e001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e00000000000001554c4c00000003010014000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000c000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff49490000000013000000000000003d01001e00050000000000000031020001000f00000000000000b0020003001300000000000000a802000500130000000000000009020007001100000000000000400200090007000000000000002b02000a000d000000000000003402000c000e00000000000000b702000e000c00000000000000ff02000f000b000000000000016702000f001600000000000000f2020010001000000000000000c502001000110000000000000159020011000e00000000000000e7020012000e0000000000000032020014000500000000000000b2020015000f00000000000000c40200170010000000000000010202001a000c000000000000004e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c31c618638c3fb8015324dafc010019001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c03070000020c00000203070000020d00000203070000020e00000203070000020f00000203070000021000000203070000021100000203070000021200000203070000021300000203070000021400000203070000021500000203070000021600000203070000021700000203070000021800000203070000021900000203070000021a00000203070000021b00000203070000021c00000203070000021d00000203070000021e00000203070000021f00000203070000022000000203070000022100000203070000022200000203070000022300000203070000022400000203070000022500000203070000022600000203070000022700000203070000022800000203070000022900000203070000022a00000203070000022b00000203070000022c00000203070000022d00000203070000022e00000203070000022f00000203070000023000000203070000023100000203070000023200000203070000023300000203070000023400000203070000023500000203070000023600000203070000023700000203070000023800000203070000023900000203070000023a00000203070000023b00000203070000023c00000203070000023d00000203070000023e00000203070000023f0000020307010b706c61796572537061776e010000020e000002040408656e67696e654f6e00000000000000294c4c0000010001020011001609789c63000000010001020011001709789c63000000010001020011001809789c63000000010001020012000009789c63000000010001020012000109789c63000000010001020012000209789c63000000010001020012000309789c63000000010001020012000409789c63000000010001020012000509789c63000000010001020012000609789c63000000010001020012000709789c63000000010001020012000809789c63000000010001020012000909789c63000000010001020012000a09789c63000000010001020012000b09789c63000000010001020012000c09789c63000000010001020012000d09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010015001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010015001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c8c68a259105100cfd208c402000b00101f789c636cd66116622dc92f4ace60676060602c656060926064000034dd038302000b001109789c6300000001000102000b00121f789c636cd66116622dc92f4ace6067606060ac6560600a6662040035c903c802000b001309789c6300000001000102000b001409789c6300000001000102000b001509789c6300000001000102000b001609789c6300000001000102000b001709789c6300000001000102000b001809789c6300000001000102000c000009789c6300000001000102000c000109789c6300000001000102000c000209789c6300000001000102000c000309789c6300000001000102000c000409789c6300000001000102000c000509789c6300000001000102000c000609789c6300000001000102000c000709789c6300000001000102000c000809789c6300000001000102000c000909789c6300000001000102000c000a09789c6300000001000102000c000b09789c6300000001000102000c000c09789c6300000001000102000c000d09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010003000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010003000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001144c4c00000007010016001760789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010017000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000064c4c9c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010018000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f901001e000360789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000460789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f901001e000a60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f901001e000b60789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9020001000909789c63000000010001020001000a09789c63000000010001020001000b09789c63000000010001020001000c09789c63000000010001020001000d09789c63000000010001020001000e09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01001c000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001c000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010005000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010008000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000914c4c00000003010014000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010017001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000b02000f000b09789c6300000001000102000f000c09789c6300000001000102000f000d09789c6300000001000102000f000e09789c6300000001000102000f000f09789c6300000001000102000f00108107789c636bd66196e0cec84fce4ead2c494cca496567606060fcc2c0c0c4c2c8009413e34c2c48ad28c84ccccb07cbfc02c930310265a478934af3b2538b0af28b4b528b8cc0b21f81b29c607d12dc498929e9f9f90539a5c51960b99770336505406616a526e717a514e42456a6168115fc871b2dc45a925f940cd1f61328cac5c2000013d4264702000f00111f789c636cd66116622dc92f4ace60676060607cc5c0c0a4c3c80000384c040c02000f001209789c6300000001000102000f001309789c6300000001000102000f001409789c6300000001000102000f001509789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010013000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000004c4c4c11001609789c63000000010001020011001709789c63000000010001020011001809789c63000000010001020012000009789c63000000010001020012000109789c63000000010001020012000209789c63000000010001020012000309789c63000000010001020012000409789c63000000010001020012000509789c63000000010001020012000609789c63000000010001020012000709789c63000000010001020012000809789c63000000010001020012000909789c63000000010001020012000a09789c63000000010001020012000b09789c63000000010001020012000c09789c63000000010001020012000d09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000301000600128169789cedd83b0ac2501445d1808d83718e164e5b881fac02828144c25b5b90c06ac271dfcadbe534cfd3f4fc7e1eafcffbb12f5f977cdffd95f13f793a2f129fa8c4ddf7e0dc7d77df63339d981e6f309d981e6f309d981e6f309d981e6f309d981e6f309d981e6f309df8cbf8757c9c39f192fbffbb8b1d9be9c4f47883e9c4f47883e9c4f47883e9c4f47883e9c4f47883e9c4f47883e9c45fc66fc2c75949335d871e6f309d981e6f309d981e6f309d981e1fabdcd9c72373f71d83dcd9c72373f71dff721083ddc960730c5e779a74e24d7eaaf8bf7c9cf389e3388ee3388ee378737e008d10fa6f010006001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010006001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff49490000000013000000000000003d01001e00050000000000000031020001000f00000000000000b0020003001300000000000000a802000500130000000000000073020007001100000000000000170200090007000000000000014202000a000d000000000000009902000c000e000000000000014c02000e000c00000000000000ec02000f000b000000000000012f02000f001600000000000000e80200100010000000000000016302001000110000000000000167020011000e000000000000018a020012000e000000000000008e020014000500000000000000b2020015000f00000000000000c40200170010000000000000010202001a000c000000000000004e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c31c618638c3fb8015324dafc010015000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010019000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000011f4c4c00000004010005001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010005001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010005001760789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010005001860789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000801000b000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000b000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000b94c4c00000006010004000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010004000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001134c4c000609789c63000000010001020005000709789c63000000010001020005000809789c63000000010001020005000909789c63000000010001020005000a09789c63000000010001020005000b09789c63000000010001020005000c09789c63000000010001020005000d09789c63000000010001020005000e09789c63000000010001020005000f09789c63000000010001020005001009789c63000000010001020005001109789c63000000010001020005001209789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4ccde6f80b1d3b51c90f969d7877fc857ce76cabec93e7472720271b671f22912cdf18638c31c618633ccbcd235f3ece392f3fca393b3918638cd7f0152acce5a201000900118100789cedd2310a80301045c180d7f18e165e5b484cb0901482dd47676159986a8bb7af4bada59c7b9d3ee3608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c678e26de6e38973fec69fe777692a164b13ff9da58943599a3894a58943599a3894a5896fdc0085bae62001000900128165789ceddbcb0a8250188551c1490fd33b3ae8b503bb1a21082aa7dafcad208435b2fcf6e0049d8efd3876ddf5fdbcdc5ef7cb4f7878f0f0e2f33b77eb38e7e3e03abcad41c5e22f71779855d56b10d7e1c5be536e10e3f6bc90bd35e012ac6f8c27b6065c99f58df1c4d6802bb3be319e78db1a3ec939df09aec3fac6f81b6c3bb832eb1be37d6c3bb832eb1be37d9c7342f7a3006ecf39b1e91b638c31c618e3390f73f687c5bfe09c43135ecd39f9c473ce43c3fa6e5f6cce7d63bc86f58d2bb3be7165d637aecc39c7204bc3ed39a7587d633c71ced2ec12b7e79c62e3fbbe000536114900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c1d42d6377e19eb1bef9973fa963daee79c90658feb39a758d9e37ace491347704e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9afac6f59c93a6be713de7a4a96f5ccf3969ea1bd7734e9acbf90462c5a64600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff49490000000016000000000000019001000c0017000000000000006e01000d0005000000000000010e01000d000b000000000000016601000d0012000000000000000801000d001600000000000000a301000e0004000000000000001c01000e000d000000000000017801000e0011000000000000018901000e0015000000000000001801000e001900000000000000a601000f0005000000000000008c01000f000b00000000000000b501000f000f000000000000008601000f00130000000000000073010010000200000000000000970100100008000000000000008f010010000e000000000000018c0100100011000000000000010301001000150000000000000001010011000000000000000000f0010011000600000000000000bb010011000c0000000000000085000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c0000000601000c000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000bc4c4ce2d2ebdf1308813325f00d77c9fa98f6bdb5d7fe1cef751c3fe1a5e7ed02d7790ece6169e2a22c4d8c31c618638c31c618638c31c618638c31c618638c31c618638c31c6189f78e9f9ca678331aef3781ccffac6c92c4d9cccfac6c9ac6f9ccb6dee429e8e90bf709d7be37fe5b162f58defc6631387f904df8b158b9359df3899f58d9359df3899f58d93b978df4f901de60e01000c00128139789cedda410a83301040d1809b1ec63bbae8b50bb196bae8428818613a798204de2a307f7679ce53ada5bcffefb17d9f03e3162e8fe597a7fa3ae638f7c6b885f58dff8b158b33b3be7166d637ceccfa1e95cf4d7e0c8e331daceffe1c673a6639ea2cb1be5b38ce74f0d590e35c10e30bac6f8c31c618638c31c618638c31c618638c31c6f87e8ef37cc98b29dc9fe3c4a66f8cbbb26dc09959df18ef6c1b7066d637ceccfac69959df18ef6c1b7066d677085e019f82488000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010018001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013000f810f789cedd23b0a80301404c0401a0fe31d2dbcb6103f68612582c546261016a6dcb7f3585b2b65fb67ecef088c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ee6324c77ae6de988afb838a7581cc1718b7dc73fdf775cdfdd71ce2db17d7fcf39b73488df5f07dbf78d738ac511bc023cd97a4e0100130010811e789cedd2310ac2501045d10f695c8c7b4ce1b685af09361616c1c2bce71918064e35c5bd5d9739c778eeeb6cb31f8c31c618638c31c618638c31c618638c31c618638c31fe1f1e97f59d97793fd583187fc1fac659fca15821e30ad637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637fe351f6b50b1388bf55dcf0f3bb69d7601001300118109789cedd23b0a80400c40c1856d3c8c77b4f0da42fc606321586ee2044260aa146f9d7b446bc7dee79ceb64e5362d4feeb1bdf3387f63fc85f58d73b1627165d637cec58ac59559df38172b1657667de35cac585c99f58d4bb0627165d637c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6ffe11ddb70bac2000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000001f020009000709789c63000000010001020009000809789c63000000010001020009000909789c63000000010001020009000a09789c63000000010001020009000b09789c63000000010001020009000c09789c63000000010001020009000d09789c63000000010001020009000e09789c63000000010001020009000f09789c63000000010001020009001024789c636ad66116622dc92f4ace6067606060b46560606262644413d581880200ac54065a020009001109789c6300000001000102000900121f789c636cd66116622dc92f4ace6067606060d4666060f2616404003374036e02000900131f789c636cd66116622dc92f4ace6067606060346760604a606400003403038d020009001409789c63000000010001020009001509789c63000000010001020009001609789c63000000010001020009001709789c63000000010001020009001809789c6300000001000102000a000009789c6300000001000102000a000109789c6300000001000102000a000209789c6300000001000102000a000309789c6300000001000102000a000409789c6300000001000102000a000509789c6300000001000102000a000609789c6300000001000102000a000709789c6300000001000102000a000809789c6300000001000102000a000909789c6300000001000102000a000a0978000000000000001b4c4c31c618638c3fb8015324dafc010014000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000007010018000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010018000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000304c4c000409789c6300000001000102001c000509789c6300000001000102001c000609789c6300000001000102001c000709789c6300000001000102001c000809789c6300000001000102001c000909789c6300000001000102001c000a09789c6300000001000102001c000b09789c6300000001000102001c000c09789c6300000001000102001c000d09789c6300000001000102001c000e09789c6300000001000102001c000f09789c6300000001000102001c001009789c6300000001000102001d000009789c6300000001000102001d000109789c6300000001000102001d000209789c6300000001000102001d000309789c6300000001000102001d000409789c6300000001000102001d000509789c6300000001000102001d000609789c6300000001000102001d000709789c6300000001000102001d000809789c6300000001000102001d000909789c6300000001000102001d000a09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01001b000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010016000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000019020011000e09789c63000000010001020011000f09789c6300000001000102001100108270789c8d52cd4ac34010dea46dd6946a5bf128a2174528fe5411f1a2480f5e44c427d86c36d9a54936ec6ea8de2c45fa003e435f43851ef4ea6378126f1e9d447a284870606067e69bbffdc61975aa9da5ba613a223a157d8631eab94fdf3d6b15e5f2fcf8717afea906d383ebadc231ea5446c74d2398dadf338c72ca99361802f63a68d5427362b5da9a24be36326131314c09120d438c5ca164e24592f62b183946424cc2ab1ec0143c12213736460d5f2833cb1a0b6cb566c645c66eb8088c7d1608710f7de6a0c3ab32a81b64513490d2df7730c286c569c4ba0f47d05caa0492f210586e4cc2982898b0bcb33310b4cf148cdb8ca5d6772901d3cfc759fc7f915afe49dd31f913733999bc00a612677e79951c31646508206f6345494f1a41a922811149688817b182c0dd9c40db828bd86935bc2c81b50a2a382cd76b7cbdcddfc4ebfbf47053ce6e62ad4d52764b496a884834e544a8a2e6c9ef510062b966a4a2bcf06e832e54d10f0ce1b96702001100111d789c636cd66116622dc92f4ace60676060603205622d464600335c0357020011001209789c63000000010001020011001309789c63000000010001020011001409789c63000000010001020011001509789c630000000100000000000001544c4c000309789c63000000010001020017000409789c63000000010001020017000509789c63000000010001020017000609789c63000000010001020017000709789c63000000010001020017000809789c63000000010001020017000909789c63000000010001020017000a09789c63000000010001020017000b09789c63000000010001020017000c09789c63000000010001020017000d09789c63000000010001020017000e09789c63000000010001020017000f09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010011000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000301001100108158789cedd6510a82401440d101215a436b688ff3d12e5a6b3095264208256a3ea723887a141cf52a5ece4d29293de6d7e239b50b8c31c6c1391d73bb724d876ebb29b78187a331de259fbab0dffbce69f4e845b83b25de98d77cc46182e8b7f3f059c718638c318ec0fddeef38ceb831d637fe77d637ae99f58d6b667de39a59dfb866d6f7dc7bb2578e73bf3d4b8c3ff0b4bebd0d786b5ef3fbad6fbc35fb3fc1788c4b9891603ca3d8691ce77270f5bc48b1fac63517ab6f5c73b1fac63fe33821638c31c618638c31c618638c31c618e3fdf11d15eba22901001100118117789cedd44b0a8020140550c149bb7003edb141db0eaca468d6c71a241c419e9ec11d5d1dfb987308cbdec6bacac018638c31c618638c31c618638c9be6d00de5d0a5ed1ef374c947086e815393acdf58bfeff151e4f07936c635fcec159f67eb37fe1beb37c63b9fd75ebf71db5cf5ad638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638cdff00c7b916878010011001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000ffffffffffffffff4c4c0000003002000c000e09789c6300000001000102000c000f1d789c636cd66116622dc92f4ace6067606060ec06e25f8c8c00381a047b02000c001009789c6300000001000102000c001109789c6300000001000102000c00121f789c636cd66116622dc92f4ace6067606060ec616060f262640000361403cc02000c00131f789c636cd66116622dc92f4ace6067606060ec6360604a61640400367103e902000c001409789c6300000001000102000c001509789c6300000001000102000c001609789c6300000001000102000c001709789c6300000001000102000c001809789c6300000001000102000d000009789c6300000001000102000d000109789c6300000001000102000d000209789c6300000001000102000d000309789c6300000001000102000d000409789c6300000001000102000d000509789c6300000001000102000d000609789c6300000001000102000d000709789c6300000001000102000d000809789c6300000001000102000d000909789c6300000001000102000d000a09789c6300000001000102000d000b09789c6300000001000102000d000c09789c6300000001000102000d000d09789c6300000001000102000d000e09789c6300000001000102000d000f09789c6300000001000102000d00101f789c636cd66116622dc92f4ace60676060605cc3c0c0c400000000000000754c4c00000003010010000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0100100010812b789cedd4510a02211440d11703d11a5a43d012fd985db4d6c06a68181cfa2d9e7604118efe8817e7cb546bc473be97d758168c31c6c9394ea5e5a9de31ee95e316c7864b7c3c8d71c3e7a59bf4bcef7b3d56b66f1d638c31c618e3bfe275f7879ce7f27878d6371e99f58d47667de391396fdf71ddf1e1eb9cee75f0b87d63dc65df18638c31c618638c31c618638c31c6b85fae18638c31c618638c31c618638c31c6382f3f005368bbe10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0205070000021800000205070000021900000205070000021a00000205070000021b00000205811b0000021c00000205070000021d00000205070000021e00000205070000021f00000205070000022000000205070000022100000205070000022200000205811b0000022300000205070000022400000205070000022500000205070000022600000205070000022700000205070000022800000205070000022900000205811b0000022a00000205070000022b00000205070000022c00000205070000022d00000205070000022e00000205070000022f00000205070000023000000205811b0000023100000205070000023200000205070000023300000205070000023400000205070000023500000205070000023600000205070000023700000205070000023800000205070000023900000205070000023a00000205070000023b00000205070000023c00000205070000023d00000205070000023e00000205070000020b00000204070000020c00000204070000020d00000204070000020e00000204070000020f00000204070000021000000204070000021100000204811b0000021200000204070000021300000204070000021400000204811b0000021500000204070000021600000204070000021700000204070000021800000204070000021900000204070000021a00000200000000000000044c4c00000002010014000f8106789cedd6410a80201005d001371da63bb6e8dac15462b869978b9027c81f1e6e842fb8af2533e2da2dee5503638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3578e65ab438b889247e77e7a20ffe7f2787ad66f8c87b2d7806766fdc6f8613f253c33eb37fec0275835b7d40100140010811a789cedd93b0a80400c40c1051b0fe31d2dbcb6b07eb05150d4cac459580253a5785d86aea9b594f96f6379ebf80797b6df7353c773fecede18df617de358fcac587de358ac6f1c8dfb238f57fc9dbd31d637cec78ac59959df38162b1667667de358ac589c99f58d13f0e92d43df3801bbec618c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ec3130184cc4400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4ccde6f80b1d3b51c90f969d7877fc857ce76cabec93e7472720271b671f22912cdf18638c31c618633ccbcd235f3ece392f3fca393b3918638cd7f0152acce5a201000900118100789cedd2310a80301045c180d7f18e165e5b484cb0901482dd47676159986a8bb7af4bada59c7b9d3ee3608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c678e26de6e38973fec69fe777692a164b13ff9da58943599a3894a58943599a3894a5896fdc0085bae62001000900128165789ceddbcb0a8250188551c1490fd33b3ae8b503bb1a21082aa7dafcad208435b2fcf6e0049d8efd3876ddf5fdbcdc5ef7cb4f7878f0f0e2f33b77eb38e7e3e03abcad41c5e22f71779855d56b10d7e1c5be536e10e3f6bc90bd35e012ac6f8c27b6065c99f58df1c4d6802bb3be319e78db1a3ec939df09aec3fac6f81b6c3bb832eb1be37d6c3bb832eb1be37d9c7342f7a3006ecf39b1e91b638c31c618e3390f73f687c5bfe09c43135ecd39f9c473ce43c3fa6e5f6cce7d63bc86f58d2bb3be7165d637aecc39c7204bc3ed39a7587d633c71ced2ec12b7e79c62e3fbbe000536114900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc010006001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0100060011813f789cedd74b0a83401005c00137394ceee822d70e1895ac041749103afd4a90815af5e70de8e33e2dcb18ebfb3eb6673f30c618638c31c618638c31c618638c31c618638c31c618638c31c618638cf1b73c1ff989eb709d9c946713accc2ec94513ac5360345fb99d66b7e1b3baffb5cb666c0d46d5992dcd4c3ab35d9a49678edee549f3d13369c6c1bb1cb743f3937cb7e3e05d9ee6bb4a8158be7f60f90ee0e84fd08c2ea359bedb7719cdf2ddbecb6896eff65d06739d5fac17355fef4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000001802000e000c09789c6300000001000102000e000d09789c6300000001000102000e000e09789c6300000001000102000e000f09789c6300000001000102000e001024789c636ad66116622dc92f4ace6067606060bcc8c0c0c4c2c888267a00220a00c15c078602000e00111f789c636cd66116622dc92f4ace60676060603cc3c0c064c0c80000378603f202000e001209789c6300000001000102000e001309789c6300000001000102000e001409789c6300000001000102000e001509789c6300000001000102000e001609789c6300000001000102000e001709789c6300000001000102000e001809789c6300000001000102000f000039789c636cd661d113e0292ec9cf4b4d2b2dca4b4c4e65626770fe70dbc73ee2b78cf952f76d87e6868a3bb76aef38c4b62a90010400bd87112f02000f000109789c6300000001000102000f000209789c6300000001000102000f000309789c6300000001000102000f000409789c6300000001000102000f000509789c6300000001000102000f000609789c6300000001000102000f000709789c6300000001000102000f000809789c6300000001000102000f000909789c6300000001000102000f000a09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0001020011001609789c63000000010001020011001709789c63000000010001020011001809789c63000000010001020012000009789c63000000010001020012000109789c63000000010001020012000209789c63000000010001020012000309789c63000000010001020012000409789c63000000010001020012000509789c63000000010001020012000609789c63000000010001020012000709789c63000000010001020012000809789c63000000010001020012000909789c63000000010001020012000a09789c63000000010001020012000b09789c63000000010001020012000c09789c63000000010001020012000d09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000003010013000f810f789cedd23b0a80301404c0401a0fe31d2dbcb6103f68612582c546261016a6dcb7f3585b2b65fb67ecef088c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c317ee6324c77ae6de988afb838a7581cc1718b7dc73fdf775cdfdd71ce2db17d7fcf39b73488df5f07dbf78d738ac511bc023cd97a4e0100130010811e789cedd2310ac2501045d10f695c8c7b4ce1b685af09361616c1c2bce71918064e35c5bd5d9739c778eeeb6cb31f8c31c618638c31c618638c31c618638c31c618638c31fe1f1e97f59d97793fd583187fc1fac659fca15821e30ad637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637ce62c5e266d637fe351f6b50b1388bf55dcf0f3bb69d7601001300118109789cedd23b0a80400c40c1856d3c8c77b4f0da42fc606321586ee2044260aa146f9d7b446bc7dee79ceb64e5362d4feeb1bdf3387f63fc85f58d73b1627165d637cec58ac59559df38172b1657667de35cac585c99f58d4bb0627165d637c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6ffe11ddb70bac2000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000006010009000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010009000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000900108179789ceddbdd0a82301806e041275d4cf7e841b71d2c2c4508358d7e5ef30165f0e0c1e7f60edc70e7d3a11c9b526b7bddee520ef5d23618e38e6bbd71697a2e61dcd53d705a0fe28f45b38ce704638c31c618638c31c618638c31c618638c31c618638c31c6781b3cff23ec9f71df074f9ece191d2cdff29d97937d5412c743beefcd04e71c36c839df9093aa9c4ab6ca396193efc5954c9e4f7bdfdc59d7b1f1336da8fbdeec8a73f3bdf6fce50bf95e17e4852cb111fcce85000000000000013b4c4c00000016020010001109789c63000000010001020010001209789c63000000010001020010001309789c63000000010001020010001409789c63000000010001020010001509789c63000000010001020010001609789c63000000010001020010001709789c63000000010001020010001809789c63000000010001020011000039789c636cd661d117e44d2acdcb4e2d2ac82f2e492d3262626770e1b22ab06f9f50c3000487e6868639372c9d7548eb6e0288cf000090840f60020011000109789c63000000010001020011000209789c63000000010001020011000309789c63000000010001020011000409789c63000000010001020011000509789c63000000010001020011000609789c63000000010001020011000709789c63000000010001020011000809789c63000000010001020011000909789c63000000010001020011000a09789c63000000010001020011000b09789c63000000010001020011000c09789c63000000010001020011000d09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000016020010001109789c63000000010001020010001209789c63000000010001020010001309789c63000000010001020010001409789c63000000010001020010001509789c63000000010001020010001609789c63000000010001020010001709789c63000000010001020010001809789c63000000010001020011000039789c636cd661d117e44d2acdcb4e2d2ac82f2e492d3262626770e1b22ab06f9f50c3000487e6868639372c9d7548eb6e0288cf000090840f60020011000109789c63000000010001020011000209789c63000000010001020011000309789c63000000010001020011000409789c63000000010001020011000509789c63000000010001020011000609789c63000000010001020011000709789c63000000010001020011000809789c63000000010001020011000909789c63000000010001020011000a09789c63000000010001020011000b09789c63000000010001020011000c09789c63000000010001020011000d09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010017001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010017001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010018000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000301001100108158789cedd6510a82401440d101215a436b688ff3d12e5a6b3095264208256a3ea723887a141cf52a5ece4d29293de6d7e239b50b8c31c6c1391d73bb724d876ebb29b78187a331de259fbab0dffbce69f4e845b83b25de98d77cc46182e8b7f3f059c718638c318ec0fddeef38ceb831d637fe77d637ae99f58d6b667de39a59dfb866d6f7dc7bb2578e73bf3d4b8c3ff0b4bebd0d786b5ef3fbad6fbc35fb3fc1788c4b9891603ca3d8691ce77270f5bc48b1fac63517ab6f5c73b1fac63fe33821638c31c618638c31c618638c31c618e3fdf11d15eba22901001100118117789cedd44b0a8020140550c149bb7003edb141db0eaca468d6c71a241c419e9ec11d5d1dfb987308cbdec6bacac018638c31c618638c31c618638c9be6d00de5d0a5ed1ef374c947086e815393acdf58bfeff151e4f07936c635fcec159f67eb37fe1beb37c63b9fd75ebf71db5cf5ad638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638cdff00c7b916878010011001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000ffffffffffffffff4c4c0000000401000e000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e00108210789cedd55d6a8350148551212f1d43c6d039de874e5b306d4d0249488b70ccdd9a2588b884e3df877e7d1ea66918bed7f3e667f9dd608c310ee7e1a3ddf2611a31c618afcb6dde9f8ffecbc799dbed90cbd02b0f182fe0b622e7dc25de0f4b1387b2347128fbcfe3505e334dc5e2de6996ccce792638823b7c07158b43d3542cde569a8ac5bb0822fe02f17bf0e5e8599e73bbe7f12f7e1882b7cead82979cb273b14f66f77e0d788fbc66b1cb38e799e0cdf24b8bd537eecd00000000000001044c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010017000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010017000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01000e000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000005010012001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010012001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000000a949490000000016000000000000019101000c0017000000000000006e01000d0005000000000000010e01000d000b000000000000018b01000d001200000000000000b101000d001600000000000000a301000e0004000000000000001c01000e000d000000000000015c01000e0011000000000000015801000e0015000000000000001801000e001900000000000000a601000f0005000000000000008c01000f000b00000000000000db01000f000f000000000000018d01000f001300000000000000d101001000020000000000000097010010000800000000000000ce010010000e00000000000000890100100011000000000000007d01001000150000000000000001010011000000000000000000f0010011000600000000000000bb010011000c000000000000014a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c00000006010015000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000fd4c4c0000000401000c000f812d789cedd7410a83301445d180932ec63d3ae8b60b5aa5d03af34fd2473c42089c51c06b4c9ef3b4aeadbdc767da9f63c218638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8875f25ce59374ee7f658ce3c1d5575e0b654f80f0becc939410cc6fa8ee09c20c6e46f55a75301eec4be067d8fccb59f575c3ef11cf08af165b6dbeb7b64aedd60e262d337b6dbeb1b57fabee7d97e03a3c0dfa901000c00108217789ceddbd10ac22000466161373d4cefe845af1d58e1245b1473eafcd513c4ea8b9a73c70862b7ebe29c31afbbf59be7cddd8d7f0ccfc8e6623f798939bc29f0fafccd7e23c702130b4b307dc370e01fd9ebb0ce54c11d72dab73d7dc3300cc3300cc3296c6546029f7b8ae1735927885e597e62a7ee64ea833fc0e1d555c29cc42c396e3883275a24bbfbfe97fdf787881d255c9ee517c981628bb0c4d98125b8e62269d577af6ba7c12e399cdd21cfd1379ccb451649835dd61c200cc3300cc3300cc3300cc3300cc37db1ce95449d5fc10a4bb24ec8f40d0fc1f40d67b1ddb2d61ff1f43d2fa7a559af587e71c01b5649b308d3f7483c549a459862459834ab307d93e6104cb1a439320fd73769c2113f003d6052ee01000c0011812c789ceddbb10a83301486d1808b0fd37774f0b505db4a17031d000000000000001e4c4c0000000102001000108713789cd5564b8f1347101e7bed1de3dd35fb4248211c3811210e61052750b2089090224591382245d4cc94673aeec7d0dd63af39907d84dd1b97fc8828bf22e427e49e4338e61c7186eaf18cb167c7866b2cb534dd5f5575d5578ff6c5939bad1beb1d2380f3408d9abef7d00bdf3f6c7ce9b9df1fbffefbed83d3df5ffef96ef8777e707273e5f4871ea47860129672150e50fb74dedca1b5d6f0e67e8dfdce501d20bff5f5e08cf9deff66e36b8c8c65e2132a01cfb014eb8e9173359a6acd621d09528d34a46e7321d688b284666f9a47aa06676d74330d92654269acd9ce892ed39b62dbcb94d68ce2a017ded675b530a9834ef5ba888150322a24fd58f1f2bb6af4dc3ee560999cee97e9ce61553da695acfb9ed159f4fd291f2be1ada73cb3aa60c63fc793d758bca8a9aeed268ab308c6a1863e45105b0838e69db54aabd56c90d0e5ae45c3c1a46c3081ba0e6a3bfd5d3f8171ca0a9516ad8d8657a77261aa720eea4ca15fc25e9850fd0a8c60c840eee5f86587575b7cb3176b182217605133e0cfa99005c40234d5c4abcc6f6c96c8e30c9f24ac6f9bfb7dc60e49b76540464f89b988695b4add5fa63127b9532ba9cfce9c644fa808b574e5d0575a1c7f45b935907262f6f83bbfd53116c5f720b04d5d07c6586abd7577f6d1d0e67f57f7c9d05a9ff20231e600000000000000e64c4c00000003010012000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000f73789cedd2310a80301004c083343e267fb4c8b7854b2236e91502cec2b130ed6dab253362dc533377618c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f85b8ee35cb9e4f51bdee70dd8bedfe70e9caabac201001200108159789cedd84d0a83301446d18050ba86aea17b74d06d17d21f1cb4410a81809ff508229c81a8ef46c4db75aab594e7be1c5edbfb90c3e53c7ff354efb887736689f53d9e7366299fb5e9cced75ffe494078b23b85cca692db63e9e9b730fe495ebeee3ace78d37e125aeb693bdf2e75d5a0d3828cdccd5103934acef4d1649e4880fcd399dec95736689f5adef63714e27f19c3334ac6f21e3a8aa848cc7734e6cfe68e3f19c13b2772c1ecf8ac5ffccc3bf0a848c43599a18638c31c618638c31c618638c31c618638c31c618638c31c618631cc80f310beafd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000701000d000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c000000000000003c4c4c0000000b02000f000b09789c6300000001000102000f000c09789c6300000001000102000f000d09789c6300000001000102000f000e09789c6300000001000102000f000f09789c6300000001000102000f00108108789c636bd66196e0cec84fce4ead2c494cca496567606060fcc2c0c0c4c2c8009493e24d2acdcb4e2d2ac82f2e492d3202cb7e04ca72826525b8931253d2f3f30b724a8b33c0722fe13a6505120b522b8a5293f38b520a72122b538bc00afe83143031021508b196e4172543b4fd048a72b180b4897182b4156426e6e583657e41d4030041db264702000f001109789c6300000001000102000f001209789c6300000001000102000f001309789c6300000001000102000f001409789c6300000001000102000f001509789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c09789c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010007001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010007001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401001a000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a001060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c8c68a2e5105100ceb408c402000b00101f789c636cd66116622dc92f4ace60676060602c656060926064000034dd038302000b001109789c6300000001000102000b00121f789c636cd66116622dc92f4ace6067606060ac6560600a6662040035c903c802000b001309789c6300000001000102000b001409789c6300000001000102000b001509789c6300000001000102000b001609789c6300000001000102000b001709789c6300000001000102000b001809789c6300000001000102000c000009789c6300000001000102000c000109789c6300000001000102000c000209789c6300000001000102000c000309789c6300000001000102000c000409789c6300000001000102000c000509789c6300000001000102000c000609789c6300000001000102000c000709789c6300000001000102000c000809789c6300000001000102000c000909789c6300000001000102000c000a09789c6300000001000102000c000b09789c6300000001000102000c000c09789c6300000001000102000c000d09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000004010011000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000201000800108217789ceddcd10a82301487f181373d4cefe845af1d189630a81869eabe9d7d900c7f17d1cef9db0c5cb7eb902e639aa6f9f53c521aa6fb3cace2e53cf36b9011bc4b8bbb664e2f65f3fd2d9a69cc3559cfcb7b67a6cd127f5de25bdc3597f3cd8dbdf9962333ee4a03d4448ec39bd69d43985313599665599665599665599665599665599665599665599665599665f97cf6993339329b6f3932fb4cbc1c89736297c17c83bf4f3631602daeb78be3cc0a7a935325df3f722bb3ec33df9c7d5e8def2fae109fcf9a8cef1fb0c8940a96b9d57cffdb4b4a1b482b49a87ce357d73203261fee7f2dccf72ef98e3279f38de8651f4ccac991a9e230a7823db0f936dfb599f4eba84de6dc29e1d97c37c89cf8e0f9011c25e69801000800118152789cedda4b0a83301486d180932ea67b74d06d0be9833aa8d05221b497df2348e04c54f2dd41c0cb79eabdb5dbfd5ceed763d9c7ed34bff2d497f73ce49118ff8cf58d9359df3899f58d9359df3899f58d8bf2be3487709d8fc7f1ac6f9ccc1ac4c9ac6f9cccfac6c9ac6f9cccfac6c9ac6f8c31c618638c31c623d8f91227b3be7132eb1b27b3be7132ffe1ffd863709d2d3e34d709228ceb6c31c6df709dd93169783cd72956df18af6c1a7032eb1be3954d034ee6b8bee72d2f9fb8ce7be3021c772ede370d86249ccbf77d00000000000000364c4c00000007010018001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9010019000060789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001794c4c00000029020012000e09789c63000000010001020012000f09789c6300000001000102001200101d789c636cd66116622dc92f4ace60676060607204624e1646003353034502001200111d789c636cd66116622dc92f4ace6067606060f205620346460034160375020012001209789c63000000010001020012001309789c63000000010001020012001409789c63000000010001020012001509789c63000000010001020012001609789c63000000010001020012001709789c63000000010001020012001809789c63000000010001020013000009789c63000000010001020013000109789c63000000010001020013000209789c63000000010001020013000309789c63000000010001020013000409789c63000000010001020013000509789c63000000010001020013000609789c63000000010001020013000709789c63000000010001020013000809789c63000000010001020013000909789c63000000010001020013000a09789c63000000010001020013000b09789c63000000010001020013000c09789c63000000010001020013000d09789c63000000010001020013000e09789c63000000010001020013000f09789c6300000001000102001300102a789c636ed66116622dc92f4ace6067606060ca076239460634d1342066606444134d87880200820f0a3f020013001100000000000000924949000000001700000000000000a401001100130000000000000181010012000200000000000000d9010012000b00000000000000fb010012000e00000000000000b80100120011000000000000019301001200150000000000000160010013000000000000000001300100130006000000000000001a010013000c000000000000005d010013000f000000000000015601001300120000000000000171010013001500000000000000d20100140000000000000000005e01001400060000000000000011010014000c000000000000012d010014000f000000000000014f0100140011000000000000019501001400150000000000000174010015000100000000000000af01001500070000000000000176010015000d000000000000016201001500130000000000000122010015001700000000000000ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c00000003010013001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010013001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4949010000000600000000000000c9010004000a00000000000000350100090003000000000000019401000c0013000000000000013d010011001000000000000000260100160003000000000000019101001d0010000000000000011e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c000209070000022b00000209070000022c00000209070000022d00000209070000022e00000209070000022f00000209070000020b00000208070000020c00000208070000020d00000208070000020e00000208070000020f00000208070000021000000208070000021100000208811b0000021200000208070000021300000208070000021400000208811b0000021500000208070000021600000208070000021700000208070000021800000208070000021900000208070000021a00000208070000021b00000208811b0000021c00000208070000021d00000208070000021e00000208070000021f00000208070000022000000208070000022100000208070000022200000208811b0000022300000208070000022400000208070000022500000208070000022600000208070000022700000208070000022800000208070000022900000208811b0000022a00000208070000022b00000208070000022c00000208070000022d00000208070000022e00000208070000022f00000208070000023000000208811b0000023100000208070000023200000208070000023300000208070000023400000208070000023500000208070000023600000208070000023700000208070000023800000208070000023900000208070000020b00000207070000020c00000207070000020d000000000000000000714c4c00000006010014001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001660789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010014001760789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010014001860789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010014001960789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c600000000000000e94c4c02070d617065786675656c68617463680007010b756e627265616b61626c650300000002090000020a0c626f6f73746572666c616d650007010b756e627265616b61626c6503000000022d0000020c0e68796c6f746c6c616e7465726e31000700000002260000020c0e68796c6f746c6c616e7465726e310007000000021f0000020c0e68796c6f746c6c616e7465726e31000700000002180000020c0e68796c6f746c6c616e7465726e310007000000020e0000020c0e68796c6f746c6c616e7465726e31000700830f0000020b0000020c070000020c0000020c070000020d0000020c070000020e0000020c070000020f0000020c07000002100000020c07000002110000020c811b000002120000020c07000002130000020c07000002140000020c811b000002150000020c07000002160000020c07000002170000020c07000002180000020c07000002190000020c070000021a0000020c070000021b0000020c811b0000021c0000020c070000021d0000020c070000021e0000020c070000021f0000020c07000002200000020c07000002210000020c07000002220000020c811b000002230000020c07000002240000020c07000002250000020c07000002260000020c07000002270000020c07000002280000020c07000002290000020c811b0000022a0000020c070000022b0000000000000000010f4c4c00000006010015000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000860789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000960789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000a60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010015000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000001344c4c31c618638c3fb8015324dafc01001a000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01001a000760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000e000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e00108210789cedd55d6a8350148551212f1d43c6d039de874e5b306d4d0249488b70ccdd9a2588b884e3df877e7d1ea66918bed7f3e667f9dd608c310ee7e1a3ddf2611a31c618afcb6dde9f8ffecbc799dbed90cbd02b0f182fe0b622e7dc25de0f4b1387b2347128fbcfe3505e334dc5e2de6996ccce792638823b7c07158b43d3542cde569a8ac5bb0822fe02f17bf0e5e8599e73bbe7f12f7e1882b7cead82979cb273b14f66f77e0d788fbc66b1cb38e799e0cdf24b8bd537eecd000000000000013c4c4c31c618638c3fb8015324dafc010019000460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019000560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000000080100080012813a789cedd3410ac2401004c0855c7c8c7ff4e0b785a8c15320a0c9c68c6d05c2429d66a77bafe7611c5b7bfcafe3f94dc7be7c99f36d051f3037fe26b7d32cf9614a7e81ebccdd893d9270fef37e77e12e8f041760b5ffa0df7506c46fb27eeb7736cbd24e9259967692ccb2b4936496a59d24b32ced2499656927c91c96e5c275ba709d5be2ad85a833890ee2a35935f16fb16a628c31c618638c31c618638c31c618638c31c618638c31c618638c31c61863bc17df018847ec5a010008001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010008001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324da00000000000000194c4c9853dec19cf20ee6946f55f13c7336d8bee379e66cb07dc7f3ccd960fb8ee799b3c1f61dcf336783ed3b9e67ce06db773ccf9c0db6ef789e391b6cdff13c7336d8bee379e66cb07dc7f3ccd960fb8ee799b3c1f61dcf336783ed3bfe926f6a1d789801000f0012811d789cedd2d10983501044d105db4997b62dbc2858c2480673168685f37df7cfb6d6ccb9fb5db78e99793f2ffca7dcd3a0be719e7b1ad437ce734f83fac679ee6950df38cf3d0dea1be7b9a7417de33cf734a86f9ce79e06f58df3dcd3a0be719e7b1ad437ce734f83d2c47916327e333f99a6bef1af59df18638c31c618638c31c618638c31c618638c31c618638c31c618638c31c61887f80bb4dbd96d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000309789c63000000010001020017000409789c63000000010001020017000509789c63000000010001020017000609789c63000000010001020017000709789c63000000010001020017000809789c63000000010001020017000909789c63000000010001020017000a09789c63000000010001020017000b09789c63000000010001020017000c09789c63000000010001020017000d09789c63000000010001020017000e09789c63000000010001020017000f09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c31c618638c3fb8015324dafc01001a000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000d001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000d001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0001020015000c09789c63000000010001020015000d09789c63000000010001020015000e09789c630000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4cc2c80000362203a602000d001124789c636ad66116622dc92f4ace6067606060dcc0c0c064c2c88026ba0b220a00c29d07bd02000d001209789c6300000001000102000d001309789c6300000001000102000d001409789c6300000001000102000d001509789c6300000001000102000d001609789c6300000001000102000d001709789c6300000001000102000d001809789c6300000001000102000e000067789c636ed661d113e0292ec9cf4b4d2b2dca4b4c4e656667707eff5fd2dee4480c03101c9a1bcae9dc6ae270882d8d17c467c0d4c104d4f16e528ddd67a5b21d8ee5c6401ddc047480ed50fc626fdaceb08321a709a843cab9d5a2e5109bf36bb00e008c3a2e6102000e000109789c6300000001000102000e000209789c6300000001000102000e000309789c6300000001000102000e000409789c6300000001000102000e000509789c6300000001000102000e000609789c6300000001000102000e000709789c6300000001000102000e000809789c6300000001000102000e000909789c6300000001000102000e000a09789c6300000001000102000e000b09789c6300000001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000009010011001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010011001760789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c00000000000000d14c4c00000003010012000b60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012000d60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff49490000000017000000000000015b0100110013000000000000017f010012000200000000000000d9010012000b00000000000000f6010012000e00000000000001540100120011000000000000012d01001200150000000000000160010013000000000000000001300100130006000000000000001a010013000c0000000000000153010013000f00000000000001410100130012000000000000009e010013001500000000000000d20100140000000000000000005e01001400060000000000000011010014000c000000000000013d010014000f00000000000000a70100140011000000000000008501001400150000000000000174010015000100000000000000af01001500070000000000000149010015000d00000000000000900100150013000000000000017e010015001700000000000000ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c00000004010019001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010019001460789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010019001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c18638c31c6f8830fc493e2f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c09789c63000000010001020013001209789c63000000010001020013001309789c63000000010001020013001409789c63000000010001020013001509789c63000000010001020013001609789c63000000010001020013001709789c63000000010001020013001809789c63000000010001020014000009789c63000000010001020014000109789c63000000010001020014000209789c63000000010001020014000309789c63000000010001020014000409789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4949010000000600000000000000c9010004000a0000000000000035010009000300000000000000f601000c0013000000000000018b010011001000000000000001700100160003000000000000019101001d001000000000000000c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000494901000000060000000000000016010004000a000000000000002d010009000300000000000000b401000c0013000000000000016101001100100000000000000183010016000300000000000000d001001d0010000000000000013300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c0000000401000e0011817e789ceddacb0a8250184561c1490fd33b36e8b503bb100e2288533b5b6d962007be91fe2c8e0a1ef7f3b24cd3e5bc2fd7e3b6c8f2caa72ee60c564630274dfb96f3cc49d3bee53c73d2b46f39cf9c34ed5bce33274dfb96f3cc49d3bee53c73d2b46f39cf9c34ed5bce33274dfb963fe6c3f34e36e769f7c0f31b4c1aac8c604adf21e60c16ce91fd6474f7210451c6acaa386cdf1dccaa8a532ce7ba37664e9af66ddf79e6a459d8f7771fff94bb4433274dfbb6ef3c73d21ce71f7c34d9a09c65fb969bf99fdf4f64f915dbb7dcccf62d37b37dcbcd6cdf7233dbb7dcccf62d37b37dcbcd6cdf7233dbb75cc185ff57c9f2caf62d37f378df671919abea01000e00127e789cedd2310ac020104541c1ebe4965e5b301ad2a44f21df11d685e9165ebbea18a5cc79d77acfc27843ee7ff03ee760fc617de30359df3899f58d9359df3899f58d9359df3899f58d9359df3899f58d9359df18638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e3f9ddf90fdab401000e001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000e000000000000013a4c4c00000019020011000e09789c63000000010001020011000f09789c630000000100010200110010826c789c8d92cd4ac340108037699b98926a2b1ea5d4a350d4f620a207057bf0523cf8049bcd26bb34c986dd0dd59b25481fa0cfd0d7a8422f7d158fde3c3a89f45090e0c2c0cecc37bf8c95f76bdd0e4ee933c1a9c63c5184612e6d8490790d523750deaf9fb55d2f4b2654463c649a99361ab95f9b91718c8af7bef8bcbdef4e37ebd6222f0d90f3b0a18524accc730ab2572fac27475278427342240e344f428dbd8896d07951cc3400caaf0e34a77270a129618451a54ba0f7dbcdce33da1d85135f6991d0186b2a398e66a18d1c2e45e245824c6a36b2b4009f805f3388b062e50c3082eb73a9b751736e1bedadf290d127c6036dde059cbf429d1d74f658853a4116455321fc8165235bd3388de8f0ed128a0b994050e102cd89711863091d5657b6a69cc0dea1dd835828f5926250fda29dd6ff93348a250de7f84f66bc5c7e00538b33bf3a4b41cc68150197d2df6f6aaa60cd299f501beec4597defdec9b8b7765737a5e1078b25b7a602001100111d789c636cd66116622dc92f4ace60676060603205622d464600335c0357020011001209789c63000000010001020011001309789c63000000010001020011001409789c63000000010001020011001509789c630000000100010200000000000000013149490000000016000000000000019001000c0017000000000000006e01000d0005000000000000010e01000d000b000000000000004301000d0012000000000000017e01000d001600000000000000a301000e0004000000000000001c01000e000d000000000000001601000e0011000000000000011901000e0015000000000000001801000e001900000000000000a601000f0005000000000000008c01000f000b00000000000000c101000f000f000000000000010b01000f001300000000000000730100100002000000000000009701001000080000000000000095010010000e000000000000014d0100100011000000000000002401001000150000000000000001010011000000000000000000f0010011000600000000000000bb010011000c000000000000016c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c00000003010010000e60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010010000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc0100100010812b789cedd4510a02211440d11703d11a5a43d012fd985db4d6c06a68181cfa2d9e7604118efe8817e7cb546bc473be97d758168c31c6c9394ea5e5a9de31ee95e316c7864b7c3c8d71c3e7a59bf4bcef7b3d56b66f1d638c31c618e3bfe275f7879ce7f27878d6371e99f58d47667de391396fdf71ddf1e1eb9cee75f0b87d63dc65df18638c31c618638c31c618638c31c6b85fae18638c31c618638c31c618638c31c6382f3f005368bbe10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000f000f60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000f0010815a789cedd25b0a82501486d113bd34865e9a4073f4a16907762183a2422be2cfbd04d9b884e3e53bbbedb2ef5b3b9e97713ace03638c7138b75577cbcb7e3f5b1ec6473cfa919b491cf6ab66c3eb369d5b3785c7aedd3d5ee49b7cbf63dfe127ef8d2379b8be6e888631c618638cf11ff2e2f79cf3f118638c31c618638c31c6b3e3e12ec618638c31c618638c31c618638c31c6f835f7f8a79c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef91a9c53be06e794afc139e56b704ef919f2014cb97fb101000f00118206789cedd54daa02311406d18093b718f7e8c06d3f883f08e2d84b5358d51042ceb43ee8ebf9b4f75af7f3ba1edffe5f6bc5c7f18e0f654e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ef604e790773ca3b9853dec19cf20ee6947730a7bc8339e51dcc29ef604e790773caff20afbfcb279f9e19e2388e6338bfde6f26fdb91dbce3439953dec19cf20ee6947730a7bc8339e51dcc29ef604e790773ca3b000000000000017b4c4c0000000401000c000f812d789cedd7410a83301445d180932ec63d3ae8b60b5aa5d03af34fd2473c42089c51c06b4c9ef3b4aeadbdc767da9f63c218638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8875f25ce59374ee7f658ce3c1d5575e0b654f80f0becc939410cc6fa8ee09c20c6e46f55a75301eec4be067d8fccb59f575c3ef11cf08af165b6dbeb7b64aedd60e262d337b6dbeb1b57fabee7d97e03a3c0dfa901000c00108217789ceddbd10ac22000466161373d4cefe845af1d58e1245b1473eafcd513c4ea8b9a73c70862b7ebe29c31afbbf59be7cddd8d7f0ccfc8e6623f798939bc29f0fafccd7e23c702130b4b307dc370e01fd9ebb0ce54c11d72dab73d7dc3300cc3300cc3296c6546029f7b8ae1735927885e597e62a7ee64ea833fc0e1d555c29cc42c396e3883275a24bbfbfe97fdf787881d255c9ee517c981628bb0c4d98125b8e62269d577af6ba7c12e399cdd21cfd1379ccb451649835dd61c200cc3300cc3300cc3300cc3300cc37db1ce95449d5fc10a4bb24ec8f40d0fc1f40d67b1ddb2d61ff1f43d2fa7a559af587e71c01b5649b308d3f7483c549a459862459834ab307d93e6104cb1a439320fd73769c2113f003d6052ee01000c0011812c789ceddbb10a83301486d1808b0fd37774f0b505db4a17031d00000000000000374c4c31c618638c3fb8015324dafc010007000c60789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c0000000401000c0013810b789cedd23b0a80301005c0401a0fe31d2dbcb6b07eb0b110221a4864169685a916de9bc71c91d2b6e7d9e738f82da761ba728ee59edbf91be312d66fdc173f6bac7ee3be58bf3be49aa1fd8cdb090debf7f7dc4e6818638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e32abc028c09a35201000c001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c001560789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc01000c001660789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4949000000001e000000000000010a01001600090000000000000048010016000f00000000000000e0010016001300000000000001970100160017000000000000012501001700060000000000000013010017000c000000000000015e0100170010000000000000012e0100170014000000000000015a0100180001000000000000014401001800080000000000000111010018000e0000000000000127010018001200000000000001400100180016000000000000016e010019000600000000000000d3010019000c0000000000000135010019001200000000000001840100190016000000000000010001001a0008000000000000009301001a000e000000000000016a01001a0012000000000000004601001b0000000000000000005f01001b000600000000000000f701001b000c00000000000000cc01001b001200000000000000d701001c000000000000000000e101001c0007000000000000010c01001c000d000000000000008d01001c0011000000000000000701001d0004000000000000003901001d000c000000000000010800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c8c68a259105100cfd208c402000b00101f789c636cd66116622dc92f4ace60676060602c656060926064000034dd038302000b001109789c6300000001000102000b00121f789c636cd66116622dc92f4ace6067606060ac6560600a6662040035c903c802000b001309789c6300000001000102000b001409789c6300000001000102000b001509789c6300000001000102000b001609789c6300000001000102000b001709789c6300000001000102000b001809789c6300000001000102000c000009789c6300000001000102000c000109789c6300000001000102000c000209789c6300000001000102000c000309789c6300000001000102000c000409789c6300000001000102000c000509789c6300000001000102000c000609789c6300000001000102000c000709789c6300000001000102000c000809789c6300000001000102000c000909789c6300000001000102000c000a09789c6300000001000102000c000b09789c6300000001000102000c000c09789c6300000001000102000c000d09789c63000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c000000040100120011810e789cedd23d0a80300c06d042170fe31d1dbcb6507f7071108a421be51542e02d4dd36f1e7329296d75b6fd1c0d638c31c618638c31c618638c31c618638c31c64f380dd3957359420d88f10bbec9f7cf38cebe71db0c76b852be71b3b0c579e557378865b037c7f94b2cdf18638c31c618638c31c618638c31c618638c31c618638c31c618638cab790549ac7d3c010012001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010012001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff494900000000120000000000000041010009000500000000000000e5010009000d0000000000000157010009001300000000000000ac0100090017000000000000000201000a0004000000000000005901000a000b000000000000001001000a000f000000000000000d01000a0011000000000000001201000a0014000000000000002301000a001800000000000000ae01000b0004000000000000013701000b000c000000000000004201000b000f000000000000004501000b001300000000000000fe01000b0017000000000000006001000c0005000000000000013e01000c000b00000000000000d501000c000f000000000000018e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4c00000004010014001160789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001260789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010014001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff4c4c00000023020014000509789c63000000010001020014000609789c63000000010001020014000709789c63000000010001020014000809789c63000000010001020014000909789c63000000010001020014000a09789c63000000010001020014000b09789c63000000010001020014000c09789c63000000010001020014000d09789c63000000010001020014000e09789c63000000010001020014000f09789c6300000001000102001400101d789c636cd66116622dc92f4ace60676060606a076206464600351c037f020014001109789c63000000010001020014001209789c63000000010001020014001309789c63000000010001020014001409789c63000000010001020014001509789c63000000010001020014001609789c63000000010001020014001709789c63000000010001020014001809789c63000000010001020015000009789c63000000010001020015000109789c63000000010001020015000209789c63000000010001020015000309789c63000000010001020015000409789c63000000010001020015000509789c63000000010001020015000609789c63000000010001020015000709789c63000000010001020015000809789c63000000010001020015000909789c63000000010001020015000a09789c63000000010001020015000b09789c6300000001000000000000017f4c4c00000004010016001360789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001460789cedc8c10900200c04c140dab14b0b4f8c5881ef39381666afac8a387f99dd608c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c3fb8015324dafc010016001560789cedc8c10900200c04c12029c72e2d3c096205bee7e05898b35755c4fc65963718638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618e30f6eca34eafb010016001660789cedc8b10900201004c10b2cc72eeddbf7116cc07836599835533ba97aebc61dc618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c618638c31c6f8830fc493e2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff00", - "world_start": "845a000004410000040f844600000000000000000000000000000000000000000000000000000000000000000042a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000447a000000000000000000000000000000000000000000000000000000000000000000b97c2fea48417a810000a97f00000f0000022c0000020111736d616c6c626f6f73746572666c616d650007010b756e627265616b61626c650300000002210000020111736d616c6c626f6f73746572666c616d650007010b756e627265616b61626c650300000002150000020111736d616c6c626f6f73746572666c616d650007010b756e627265616b61626c650300000002390000020411617065786361707461696e7363686169720007010b756e627265616b61626c65030000000231000002040c6170657873686970646f6f720007000000020e000002040a74656c65706f727465720007010b756e627265616b61626c6503000000022d000002060b7465636873746174696f6e0007010b756e627265616b61626c65030000000218000002060e61706578736869706c6f636b65720007030b756e627265616b61626c650300056c6576656c04020d7472656173757265506f6f6c7306010515676c6974636853746172746572547265617375726500000235000002070d617065786675656c68617463680007010b756e627265616b61626c650300000002090000020a0c626f6f73746572666c616d650007010b756e627265616b61626c6503000000022d0000020c0e68796c6f746c6c616e7465726e31000700000002260000020c0e68796c6f746c6c616e7465726e310007000000021f0000020c0e68796c6f746c6c616e7465726e31000700000002180000020c0e68796c6f746c6c616e7465726e310007000000020e0000020c0e68796c6f746c6c616e7465726e31000700830f0000020b0000020c070000020c0000020c070000020d0000020c070000020e0000020c070000020f0000020c07000002100000020c07000002110000020c811b000002120000020c07000002130000020c07000002140000020c811b000002150000020c07000002160000020c07000002170000020c07000002180000020c07000002190000020c070000021a0000020c070000021b0000020c811b0000021c0000020c070000021d0000020c070000021e0000020c070000021f0000020c07000002200000020c07000002210000020c07000002220000020c811b000002230000020c07000002240000020c07000002250000020c07000002260000020c07000002270000020c07000002280000020c07000002290000020c811b0000022a0000020c070000022b0000020c070000022c0000020c070000022d0000020c070000022e0000020c070000022f0000020c070000020b0000020b070000020c0000020b070000020d0000020b070000020e0000020b070000020f0000020b07000002100000020b07000002110000020b811b000002120000020b07000002130000020b07000002140000020b811b000002150000020b07000002160000020b07000002170000020b07000002180000020b07000002190000020b070000021a0000020b070000021b0000020b811b0000021c0000020b070000021d0000020b070000021e0000020b070000021f0000020b07000002200000020b07000002210000020b07000002220000020b811b000002230000020b07000002240000020b07000002250000020b07000002260000020b07000002270000020b07000002280000020b07000002290000020b811b0000022a0000020b070000022b0000020b070000022c0000020b070000022d0000020b070000022e0000020b070000022f0000020b070000020b0000020a070000020c0000020a070000020d0000020a070000020e0000020a070000020f0000020a07000002100000020a07000002110000020a811b000002120000020a07000002130000020a07000002140000020a811b000002150000020a07000002160000020a07000002170000020a07000002180000020a07000002190000020a070000021a0000020a070000021b0000020a811b0000021c0000020a070000021d0000020a070000021e0000020a070000021f0000020a07000002200000020a07000002210000020a07000002220000020a811b000002230000020a07000002240000020a07000002250000020a07000002260000020a07000002270000020a07000002280000020a07000002290000020a811b0000022a0000020a070000022b0000020a070000022c0000020a070000022d0000020a070000022e0000020a070000022f0000020a070000020b00000209070000020c00000209070000020d00000209070000020e00000209070000020f00000209070000021000000209070000021100000209811b0000021200000209070000021300000209070000021400000209811b0000021500000209070000021600000209070000021700000209070000021800000209070000021900000209070000021a00000209070000021b00000209811b0000021c00000209070000021d00000209070000021e00000209070000021f00000209070000022000000209070000022100000209070000022200000209811b0000022300000209070000022400000209070000022500000209070000022600000209070000022700000209070000022800000209070000022900000209811b0000022a00000209070000022b00000209070000022c00000209070000022d00000209070000022e00000209070000022f00000209070000020b00000208070000020c00000208070000020d00000208070000020e00000208070000020f00000208070000021000000208070000021100000208811b0000021200000208070000021300000208070000021400000208811b0000021500000208070000021600000208070000021700000208070000021800000208070000021900000208070000021a00000208070000021b00000208811b0000021c00000208070000021d00000208070000021e00000208070000021f00000208070000022000000208070000022100000208070000022200000208811b0000022300000208070000022400000208070000022500000208070000022600000208070000022700000208070000022800000208070000022900000208811b0000022a00000208070000022b00000208070000022c00000208070000022d00000208070000022e00000208070000022f00000208070000023000000208811b0000023100000208070000023200000208070000023300000208070000023400000208070000023500000208070000023600000208070000023700000208070000023800000208070000023900000208070000020b00000207070000020c00000207070000020d00000207070000020e00000207070000020f00000207070000021000000207070000021100000207811b0000021200000207070000021300000207070000021400000207811b0000021500000207070000021600000207070000021700000207070000021800000207070000021900000207070000021a00000207070000021b00000207811b0000021c00000207070000021d00000207070000021e00000207070000021f00000207070000022000000207070000022100000207070000022200000207811b0000022300000207070000022400000207070000022500000207070000022600000207070000022700000207070000022800000207070000022900000207811b0000022a00000207070000022b00000207070000022c00000207070000022d00000207070000022e00000207070000022f00000207070000023000000207811b0000023100000207070000023200000207070000023300000207070000023400000207070000023500000207070000023600000207070000023700000207070000023800000207070000023900000207070000023a00000207070000023b00000207070000020b00000206070000020c00000206070000020d00000206070000020e00000206070000020f00000206070000021000000206070000021100000206811b0000021200000206070000021300000206070000021400000206811b0000021500000206070000021600000206070000021700000206070000021800000206070000021900000206070000021a00000206070000021b00000206811b0000021c00000206070000021d00000206070000021e00000206070000021f00000206070000022000000206070000022100000206070000022200000206811b0000022300000206070000022400000206070000022500000206070000022600000206070000022700000206070000022800000206070000022900000206811b0000022a00000206070000022b00000206070000022c00000206070000022d00000206070000022e00000206070000022f00000206070000023000000206811b0000023100000206070000023200000206070000023300000206070000023400000206070000023500000206070000023600000206070000023700000206070000023800000206070000023900000206070000023a00000206070000023b00000206070000023c00000206070000023d00000206070000020b00000205070000020c00000205070000020d00000205070000020e00000205070000020f00000205070000021000000205070000021100000205811b0000021200000205070000021300000205070000021400000205811b0000021500000205070000021600000205070000021700000205070000021800000205070000021900000205070000021a00000205070000021b00000205811b0000021c00000205070000021d00000205070000021e00000205070000021f00000205070000022000000205070000022100000205070000022200000205811b0000022300000205070000022400000205070000022500000205070000022600000205070000022700000205070000022800000205070000022900000205811b0000022a00000205070000022b00000205070000022c00000205070000022d00000205070000022e00000205070000022f00000205070000023000000205811b0000023100000205070000023200000205070000023300000205070000023400000205070000023500000205070000023600000205070000023700000205070000023800000205070000023900000205070000023a00000205070000023b00000205070000023c00000205070000023d00000205070000023e00000205070000020b00000204070000020c00000204070000020d00000204070000020e00000204070000020f00000204070000021000000204070000021100000204811b0000021200000204070000021300000204070000021400000204811b0000021500000204070000021600000204070000021700000204070000021800000204070000021900000204070000021a00000204070000021b00000204811b0000021c00000204070000021d00000204070000021e00000204070000021f00000204070000022000000204070000022100000204070000022200000204811b0000022300000204070000022400000204070000022500000204070000022600000204070000022700000204070000022800000204070000022900000204811b0000022a00000204070000022b00000204070000022c00000204070000022d00000204070000022e00000204070000022f00000204070000023000000204811b0000023100000204070000023200000204070000023300000204070000023400000204070000023500000204070000023600000204070000023700000204070000023800000204070000023900000204070000023a00000204070000023b00000204070000023c00000204070000023d00000204070000023e00000204077f0000020a0000020d070000020b0000020d070000020c0000020d070000020d0000020d070000020e0000020d070000020f0000020d07000002100000020d07000002110000020d07000002120000020d07000002130000020d07000002140000020d07000002150000020d07000002160000020d07000002170000020d07000002180000020d07000002190000020d070000021a0000020d070000021b0000020d070000021c0000020d070000021d0000020d070000021e0000020d070000021f0000020d07000002200000020d07000002210000020d07000002220000020d07000002230000020d07000002240000020d07000002250000020d07000002260000020d07000002270000020d07000002280000020d07000002290000020d070000022a0000020d070000022b0000020d070000022c0000020d070000022d0000020d070000022e0000020d070000022f0000020d07000002300000020d07000002310000020d070000020a0000020c07000002300000020c07000002310000020c070000020a0000020b07000002300000020b07000002310000020b070000020a0000020a07000002300000020a07000002310000020a070000020a000002090700000230000002090700000231000002090700000232000002090a00000233000002090a00000234000002090a00000235000002090a00000236000002090a00000237000002090a00000238000002090a00000239000002090a0000020a00000208070000023a000002080a0000023b000002080a0000020a00000207070000023c000002070a0000023d000002070a0000020a00000206070000023e000002060a0000023f000002060a0000020a00000205070000023f000002050a0000020a00000204070000023f000002040a0000020a00000203070000020b00000203070000020c00000203070000020d00000203070000020e00000203070000020f00000203070000021000000203070000021100000203070000021200000203070000021300000203070000021400000203070000021500000203070000021600000203070000021700000203070000021800000203070000021900000203070000021a00000203070000021b00000203070000021c00000203070000021d00000203070000021e00000203070000021f00000203070000022000000203070000022100000203070000022200000203070000022300000203070000022400000203070000022500000203070000022600000203070000022700000203070000022800000203070000022900000203070000022a00000203070000022b00000203070000022c00000203070000022d00000203070000022e00000203070000022f00000203070000023000000203070000023100000203070000023200000203070000023300000203070000023400000203070000023500000203070000023600000203070000023700000203070000023800000203070000023900000203070000023a00000203070000023b00000203070000023c00000203070000023d00000203070000023e00000203070000023f0000020307010b706c61796572537061776e010000020e00000204916a817f02095716a727bbd6d53f8000003f8000003f8000003f8000003f0c8c8d3f0c8c8d3f34b4b53f8000003ef0f0f23ef0f0f23f34b4b53f8000003f3ebebf3f3ebebf3f52d2d43f8000003f2aaaab3f2aaaab3f52d2d43f8000003f20a0a13ef0f0f23f34b4b53f8000003f0c8c8d3ec8c8ca3f34b4b53f8000003e20a0a1000000003e70f0f23f8000003d20a0a1000000003da0a0a13f8000003f0c8c8d3f0c8c8d3f34b4b53f8000003f3ebebf3f3ebebf3f52d2d43f8000003f20a0a13ef0f0f23f34b4b53f8000003dd0d0d23dd0d0d23df8f8fa3f80000044edae5244c80000457a000005616c706861fce5da4aff4b6886fe62174d00000005000000000000000000004284211c00000000008e60333fbb59db182f736b792f6f72626974616c732f636c6f7564342e706e673e55a5f84444ae0b4043e4db182f736b792f6f72626974616c732f636c6f7564322e706e673e7eb1344446d6f34048af6c182f736b792f6f72626974616c732f636c6f7564332e706e673e6c13ab4447bd3340b9e067182f736b792f6f72626974616c732f636c6f7564342e706e673e868453443ed6dd3f7a293f182f736b792f6f72626974616c732f636c6f7564322e706e673e8cf2ca443c467c3e5b44fb182f736b792f6f72626974616c732f636c6f7564332e706e673e83061844391bce40b04bea182f736b792f6f72626974616c732f636c6f7564342e706e673e8adf0b44435f4d3f015d05182f736b792f6f72626974616c732f636c6f7564322e706e673e5be03a44425bbf3ffe1ae8182f736b792f6f72626974616c732f636c6f7564332e706e673e852e1a444988bc3fa92d36182f736b792f6f72626974616c732f636c6f7564322e706e673e5d44144439a3d73e18e0f0182f736b792f6f72626974616c732f636c6f7564342e706e673e80deab443a1e174078545b182f736b792f6f72626974616c732f636c6f7564342e706e673e96f4184449ab6b3fe0ec39182f736b792f6f72626974616c732f636c6f7564322e706e673e6ef49c4444bcab4042c04c182f736b792f6f72626974616c732f636c6f7564322e706e673e93bf844448915e40919336182f736b792f6f72626974616c732f636c6f7564332e706e673e5da3b1443f19b93e9e4d7b182f736b792f6f72626974616c732f636c6f7564322e706e673e8eb92c444335e240b7a918182f736b792f6f72626974616c732f636c6f7564332e706e673e7506ce443b90bb40281704182f736b792f6f72626974616c732f636c6f7564332e706e673e92f4a44444f1ec409cbcf2182f736b792f6f72626974616c732f636c6f7564342e706e673e7a848b443bb8fc401590be182f736b792f6f72626974616c732f636c6f7564322e706e673e90594e4445c7b040ab580a182f736b792f6f72626974616c732f636c6f7564342e706e673e713c834443563f40b779db182f736b792f6f72626974616c732f636c6f7564322e706e673e5c9c44443e46fd40852efe182f736b792f6f72626974616c732f636c6f7564322e706e673e58edc14446c2be4081ffe1182f736b792f6f72626974616c732f636c6f7564322e706e673e53fcb144469cb740ab3018182f736b792f6f72626974616c732f636c6f7564342e706e673e786c3e444569df4008a010182f736b792f6f72626974616c732f636c6f7564322e706e673e7b493c4439bf7f3f5a382d182f736b792f6f72626974616c732f636c6f7564322e706e673e77f674443b4e5a40145246182f736b792f6f72626974616c732f636c6f7564342e706e673e79a1b4443e2b043f9653d2182f736b792f6f72626974616c732f636c6f7564342e706e673e939e7d4449706740be364e182f736b792f6f72626974616c732f636c6f7564342e706e673e7afd2844426d6f40c10354182f736b792f6f72626974616c732f636c6f7564322e706e673e747291443edf973ffdaeac182f736b792f6f72626974616c732f636c6f7564332e706e673e8e3a9d443a8b4f40458dee182f736b792f6f72626974616c732f636c6f7564332e706e673e6d95394447f3d93f945ee6182f736b792f6f72626974616c732f636c6f7564342e706e673e9010b644459a6f40ad9264182f736b792f6f72626974616c732f636c6f7564322e706e673e4cfaab44481c6f3f682c7b182f736b792f6f72626974616c732f636c6f7564332e706e673e66c1844448dcf240b63501182f736b792f6f72626974616c732f636c6f7564322e706e673e5a52c2443cf7963eb4071f182f736b792f6f72626974616c732f636c6f7564342e706e673e5ff118443c78bf407056b0182f736b792f6f72626974616c732f636c6f7564342e706e673e8fc6414441809a40181499182f736b792f6f72626974616c732f636c6f7564342e706e673e67b9954446f83940a0721b182f736b792f6f72626974616c732f636c6f7564342e706e673e95a05e443bd7df40822f46182f736b792f6f72626974616c732f636c6f7564322e706e673e890898444120af40a1e924182f736b792f6f72626974616c732f636c6f7564332e706e673e8811be4439aca040b7cb06182f736b792f6f72626974616c732f636c6f7564322e706e673e807eb844464b73403c62a0182f736b792f6f72626974616c732f636c6f7564332e706e673e518045443cf4be406d0753182f736b792f6f72626974616c732f636c6f7564332e706e673e748ff2443a66093f746368182f736b792f6f72626974616c732f636c6f7564322e706e673e7fd3ee444728843f96fdab182f736b792f6f72626974616c732f636c6f7564342e706e673e9408cd4449ca5940078739182f736b792f6f72626974616c732f636c6f7564322e706e673e961706443f8d2a3fa5edcb182f736b792f6f72626974616c732f636c6f7564342e706e673e90fa5c443db5b040836567182f736b792f6f72626974616c732f636c6f7564322e706e673e94a50944395b254104d68143313f8110d83fb4d6483fca8bf65e142850214880c9be0b61a8be8c0a667e99f113cca9e6983ff4ef903fcca6b007c95949f3e8e2593f9654de3fb9e852004229b4a446433ac941200000030000000000000000000000003e22a38f00000000000000000000000000000000000000003ab94ae90f0100000000000000000000000000004403800044014000040a6675656c2e6c6576656c04861a086675656c2e6d6178048f5011696e76696e6369626c65506c6179657273030108656e67696e654f6e03000000000100" -} \ No newline at end of file diff --git a/tests/packet_tests.py b/tests/packet_tests.py deleted file mode 100644 index 6ad4350..0000000 --- a/tests/packet_tests.py +++ /dev/null @@ -1,227 +0,0 @@ -import json -from nose.tools import * - -from packets import * - -''' -Tests for packet type 0x01: Protocol Version, Server -> Client -''' - - -class ProtocolVersionTest(unittest.TestCase): - def testParseBuild(self): - packet = "00000274".decode("hex") - parsed = protocol_version().parse(packet) - assert_equal(parsed.server_build, 628) - assert_equal(protocol_version().build(parsed), packet) - - -''' -Tests for packet type 0x02: Connect Response, Server -> Client -''' - - -class ConnectRsponseTest(unittest.TestCase): - def testParseBuild(self): - packet = "010100".decode("hex") - parsed = connect_response().parse(packet) - - assert_equal(connect_response().build(parsed), packet) - - -''' -Tests for packet type 0x03: Server Disconnect, Server -> Client -''' - - -class ServerDisconnectTest(unittest.TestCase): - def testParseBuild(self): - raise "not implemented, no test data available" - - -''' -Tests for packet type 0x04: Handshake Challenge, Server -> Client -''' - - -class HandshakeChallangeTest(unittest.TestCase): - def testParseBuild(self): - packet = "00203575416369525a6b6d774b556b656b336b72552b73324c54765048453676325000001388".decode("hex") - parsed = handshake_challenge().parse(packet) - assert_is_instance(parsed.claim_message, str) - assert_is_instance(parsed.salt, str) - assert_is_instance(parsed.round_count, int) - assert_equal(handshake_challenge().build(parsed), packet) - - -''' -Tests for packet type 0x05: Chat Received, Server -> Client -''' - - -class ChatReceivedTest(unittest.TestCase): - def testChatReceived(self): - packet = "TODO: NO TEST DATA".decode("hex") - parsed = chat_received().parse(packet) - - assert_equal(chat_received().build(parsed), packet) - - -''' -Tests for packet type 0x06: Universe Time Update, Server -> Client -''' - - -class UniverseTimeUpdateTest(unittest.TestCase): - def testParseBuild(self): - packet = "85e2c976".decode("hex") - parsed = universe_time_update().parse(packet) - - assert_equal(universe_time_update().build(parsed), packet) - - -''' -Tests for packet type 0x07: Client Connect, Server -> Client, compressed -''' - - -class ClientConnectTest(unittest.TestCase): - def testParseBuild(self): - with open("tests/large_packets.json", "r+") as large_packets: - packet = json.load(large_packets)['client_connect'].decode("hex") - parsed = client_connect().parse(packet) - - assert_equal(client_connect().build(parsed), packet) - - -''' -Tests for packet type 0x08: Client Disconnect, Server -> Client, compressed -''' - - -class ClientDisconnectTest(unittest.TestCase): - def testParseBuild(self): - packet = "00".decode("hex") - parsed = client_disconnect().parse(packet) - - assert_equal(client_disconnect().build(parsed), packet) - - -''' -Tests for packet types 0x09: Handshake Response, Client -> Server -''' - - -class HandshakeResponseTest(unittest.TestCase): - def testParseBuild(self): - packet = "002c345639357a77384158783633425433316a4c755955346e786f6e7970374b4179526a4a794f42516c6330553d".decode( - "hex") - parsed = handshake_response().parse(packet) - assert_is_instance(parsed.claim_response, str) - assert_is_instance(parsed.hash, str) - assert_equal(handshake_response().build(parsed), packet) - - -''' -Tests for packet types 0x0A: Warp Command, Client -> Server -''' - - -class WarpCommandTest(unittest.TestCase): - def testMoveShip(self): - packet = "0000000105616c706861fce5da4aff4b6886fe62174d000000050000000000".decode("hex") - parsed = warp_command().parse(packet) - assert_equal(parsed.world_coordinate.sector, 'alpha') - assert_equal(parsed.world_coordinate.planet, 5) - assert_equal(parsed.warp_type, 'MOVE_SHIP') - built_packet = warp_command().build(parsed) - assert_equal(packet, built_packet) - - def testParseUp(self): - packet = "0000000200000000000000000000000000000000000000000000".decode("hex") - parsed = warp_command().parse(packet) - - assert_equal(parsed.world_coordinate.sector, '') - assert_equal(parsed.world_coordinate.planet, 0) - assert_equal(parsed.player, '') - assert_equal(parsed.warp_type, 'WARP_UP') - - built_packet = warp_command().build(parsed) - assert_equal(packet, built_packet) - - - def testWarpOtherShip(self): - packet = "00000003000000000000000000000000000000000000000000056d61666669".decode("hex") - parsed = warp_command().parse(packet) - assert_is_not(parsed.player, '') - assert_equal(parsed.warp_type, 'WARP_OTHER_SHIP') - - built_packet = warp_command().build(parsed) - assert_equal(packet, built_packet) - - def testWarpDown(self): - packet = "0000000400000000000000000000000000000000000000000000".decode("hex") - parsed = warp_command().parse(packet) - assert_equal(parsed.warp_type, 'WARP_DOWN') - - built_packet = warp_command().build(parsed) - assert_equal(packet, built_packet) - - def testWarpDownHomePlanet(self): - packet = "0000000500000000000000000000000000000000000000000000".decode("hex") - parsed = warp_command().parse(packet) - assert_equal(parsed.warp_type, 'WARP_HOME') - - built_packet = warp_command().build(parsed) - assert_equal(packet, built_packet) - - -''' -Tests for packet types 0x0B: Chat Sent, Client -> Server -''' - - -class ChatSentTest(unittest.TestCase): - def testParseBuild(self): - packet = "0b68656c6c6f20776f726c6400".decode("hex") - parsed = chat_sent().parse(packet) - assert_equal(parsed.message, "hello world") - assert_equal(chat_sent().build(parsed), packet) - - -''' -Tests for packet types 0x0C: Client Context Update , Client -> Server -''' - - -class ClientContextUpdateTest(unittest.TestCase): - def testParseBuild(self): - raise "not yet understood" - - -''' -Tests for packet types 0x0D: World Start, Server -> Client -''' - - -class WorldStartTest(unittest.TestCase): - def testParseBuild(self): - with open("tests/large_packets.json", "r+") as large_packets: - packet = json.load(large_packets)['world_start'].decode("hex") - parsed = world_start().parse(packet) - - assert_equal(world_start().build(parsed), packet) - - -''' -Tests for packet types 0x0E: World Stop, Server -> Client -''' - - -class WorldStopTest(unittest.TestCase): - def testParseBuild(self): - packet = "0752656d6f766564".decode("hex") - parsed = world_stop().parse(packet) - assert_equal(parsed.status, "Removed") - assert_equal(world_stop().build(parsed), packet) - From ca070f7402cfc29b6d8cf2b6479e9897c057e445 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 1 Feb 2015 03:46:11 -0500 Subject: [PATCH 58/95] code refactoring, fixing client DC and crash bugs. Brought in IRC bot for testing --- base_plugin.py | 18 ++- packets/packet_types.py | 18 +-- plugins/announcer_plugin/announcer_plugin.py | 2 +- plugins/core/player_manager/plugin.py | 7 +- plugins/irc_plugin/__init__.py | 1 + plugins/irc_plugin/irc_manager.py | 76 +++++++++++ plugins/irc_plugin/irc_plugin.py | 67 ++++++++++ plugins/warpy_plugin/warpy_plugin.py | 12 +- server.py | 127 ++++++++++--------- utility_functions.py | 4 +- 10 files changed, 245 insertions(+), 87 deletions(-) create mode 100644 plugins/irc_plugin/__init__.py create mode 100644 plugins/irc_plugin/irc_manager.py create mode 100644 plugins/irc_plugin/irc_plugin.py diff --git a/base_plugin.py b/base_plugin.py index cfc6b29..f15d210 100644 --- a/base_plugin.py +++ b/base_plugin.py @@ -149,7 +149,7 @@ def on_burn_container(self, data): def on_clear_container(self, data): return True - def on_world_update(self, data): + def on_world_client_state_update(self, data): return True def on_entity_create(self, data): @@ -182,10 +182,13 @@ def on_damage_notification(self, data): def on_client_connect(self, data): return True - def on_client_disconnect(self, player): + def on_client_disconnect_request(self, player): return True - def on_warp_command(self, data): + def on_player_warp(self, data): + return True + + def on_central_structure_update(self, data): return True def after_protocol_version(self, data): @@ -293,7 +296,7 @@ def after_burn_container(self, data): def after_clear_container(self, data): return True - def after_world_update(self, data): + def after_world_client_state_update(self, data): return True def after_entity_create(self, data): @@ -326,10 +329,13 @@ def after_damage_notification(self, data): def after_client_connect(self, data): return True - def after_client_disconnect(self, data): + def after_client_disconnect_request(self, data): + return True + + def after_player_warp(self, data): return True - def after_warp_command(self, data): + def after_central_structure_update(self, data): return True def __repr__(self): diff --git a/packets/packet_types.py b/packets/packet_types.py index 67145cd..4ae9bd7 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -131,13 +131,12 @@ def _decode(self, obj, context): star_string("salt"), SBInt32("round_count")) -# Needs attention +# Needs to be corrected to include 'celestial information' as well as proper reject +# sucess handling. connect_response = lambda name="connect_response": Struct(name, Flag("success"), VLQ("client_id"), - star_string("reject_reason") - # may need to add something here CelestialBaseInformation - ) + star_string("reject_reason")) # corrected. needs testing chat_received = lambda name="chat_received": Struct(name, @@ -176,8 +175,8 @@ def _decode(self, obj, context): server_disconnect = lambda name="server_disconnect": Struct(name, star_string("reason")) -client_disconnect = lambda name="client_disconnect": Struct(name, - Byte("data")) +client_disconnect_request = lambda name="client_disconnect_request": Struct(name, + Byte("data")) celestial_request = lambda name="celestial_request": Struct(name, GreedyRange(star_string("requests"))) @@ -189,7 +188,7 @@ def _decode(self, obj, context): SBInt32("planet"), SBInt32("satellite")) -warp_command = lambda name="warp_command": Struct(name, +player_warp = lambda name="player_warp": Struct(name, Enum(UBInt8("warp_type"), WARP_TO=0, WARP_RETURN=1, @@ -198,7 +197,7 @@ def _decode(self, obj, context): WARP_TO_OWN_SHIP=4), WarpVariant("world_id")) -warp_command_write = lambda t, world_id: warp_command().build( +player_warp_write = lambda t, world_id: player_warp().build( Container( warp_type=t, world_id=world_id)) @@ -257,4 +256,7 @@ def _decode(self, obj, context): Struct("key", Variant("value")))) +central_structure_update = lambda name="central_structure_update": Struct(name, + Variant("structureData")) + projectile = DictVariant("projectile") diff --git a/plugins/announcer_plugin/announcer_plugin.py b/plugins/announcer_plugin/announcer_plugin.py index d731daa..9a35421 100644 --- a/plugins/announcer_plugin/announcer_plugin.py +++ b/plugins/announcer_plugin/announcer_plugin.py @@ -25,7 +25,7 @@ def after_connect_response(self, data): self.logger.exception("Unknown error in after_connect_response.") return - def on_client_disconnect(self, data): + def on_client_disconnect_request(self, data): if self.protocol.player is not None: self.factory.broadcast(self.protocol.player.colored_name(self.config.colors) + " logged out.", 0, "Announcer") diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 369ea69..62e4ca1 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -7,7 +7,7 @@ from base_plugin import SimpleCommandPlugin from manager import PlayerManager, Banned, Player, permissions, UserLevels -from packets import client_connect, connect_response, warp_command +from packets import client_connect, connect_response import packets from utility_functions import extract_name, build_packet, Planet @@ -53,7 +53,7 @@ def on_client_connect(self, data): duplicate_player = self.player_manager.get_by_org_name(client_data.name) if duplicate_player is not None and duplicate_player.uuid != client_data.uuid: raise NameError( - "The name of this character is already taken on the server!\nPlease, create a new character with a different name or use Starcheat and change the name.") + "The name of this character is already taken on the server!\nPlease, create a new character with a different name or talk to an administrator.") self.logger.info("Got a duplicate original player name, asking player to change character name!") #rnd_append = str(randrange(10, 99)) #original_name += rnd_append @@ -118,6 +118,7 @@ def after_world_start(self, data): # may need to add more world types in here world_start = packets.world_start().parse(data.data) # self.logger.debug("World start: %s", world_start) # debug world packets + # self.logger.debug("World start raw: %s", data.data.encode('hex')) # debug world packets if 'ship.maxFuel' in world_start['world_properties']: self.logger.info("Player %s is now on a ship.", self.protocol.player.name) self.protocol.player.on_ship = True @@ -134,7 +135,7 @@ def after_world_start(self, data): coords['planet'], coords['satellite']) self.protocol.player.planet = str(planet) - def on_client_disconnect(self, player): + def on_client_disconnect_request(self, player): if self.protocol.player is not None and self.protocol.player.logged_in: self.logger.info("Player disconnected: %s", self.protocol.player.name) self.protocol.player.logged_in = False diff --git a/plugins/irc_plugin/__init__.py b/plugins/irc_plugin/__init__.py new file mode 100644 index 0000000..d2369c3 --- /dev/null +++ b/plugins/irc_plugin/__init__.py @@ -0,0 +1 @@ +from irc_plugin import IrcPlugin diff --git a/plugins/irc_plugin/irc_manager.py b/plugins/irc_plugin/irc_manager.py new file mode 100644 index 0000000..1f1b024 --- /dev/null +++ b/plugins/irc_plugin/irc_manager.py @@ -0,0 +1,76 @@ +# twisted imports +from twisted.words.protocols import irc +from twisted.internet import reactor, protocol +from uuid import uuid4 + + +class StarryPyIrcBot(irc.IRCClient): + + def __init__(self, logger, nickname, nickserv_password, factory, broadcast_target, colors, echo_from_channel): + self.logger = logger + self.nickname = nickname + self.nickserv_password = nickserv_password + self.id = str(uuid4().hex) + self.factory = factory + self.broadcast_target = broadcast_target + self.colors = colors + self.echo_from_channel = echo_from_channel + + def signedOn(self): + if self.nickserv_password: + self.msg("NickServ", "identify %s" % self.nickserv_password) + if self.factory.target.startswith("#"): + self.join(self.factory.target) + else: + self.send_greeting(self.factory.target) + + self.logger.info("Connected to IRC") + + def joined(self, target): + self.send_greeting(target) + + def send_greeting(self, target): + self.msg(target, "%s is live!" % self.nickname) + + def privmsg(self, user, target, msg): + user = user.split('!', 1)[0] + self.logger.info("IRC Message <%s>: %s" % (user, msg)) + if self.echo_from_channel: + self.broadcast_target.broadcast("%s%s: <%s>: %s%s" % ( + self.colors['irc'], + target, + user, + msg, + self.colors['default'], + )) + + def action(self, user, target, msg): + user = user.split('!', 1)[0] + self.logger.info("IRC Action: %s %s" % (user, msg)) + + +class StarryPyIrcBotFactory(protocol.ClientFactory): + def __init__(self, target, logger, nickname, nickserv_password, broadcast_target, colors, echo_from_channel): + self.nickname = nickname + try: + self.nickserv_password = nickserv_password + except AttributeError: + self.nickserv_password = None + + self.target = target + self.broadcast_target = broadcast_target + self.colors = colors + self.logger = logger + self.irc_clients = {} + self.echo_from_channel = echo_from_channel + + def buildProtocol(self, addr): + irc_client = StarryPyIrcBot(self.logger, self.nickname, self.nickserv_password, self, self.broadcast_target, self.colors, self.echo_from_channel) + self.irc_clients[irc_client.id] = irc_client + return irc_client + + def clientConnectionLost(self, connector, reason): + connector.connect() + + def clientConnectionFailed(self, connector, reason): + self.logger.error("connection failed: %s" % reason) diff --git a/plugins/irc_plugin/irc_plugin.py b/plugins/irc_plugin/irc_plugin.py new file mode 100644 index 0000000..2ee2655 --- /dev/null +++ b/plugins/irc_plugin/irc_plugin.py @@ -0,0 +1,67 @@ +from twisted.internet import reactor + +from base_plugin import BasePlugin +from packets import chat_sent, client_connect +from irc_manager import StarryPyIrcBotFactory + +#TODO: multiple channels, multiple servers + + +class IrcPlugin(BasePlugin): + name = "irc" + + def __init__(self, *args, **kwargs): + super(IrcPlugin, self).__init__(*args, **kwargs) + self.web_factory = None + + def activate(self): + super(IrcPlugin, self).activate() + + self.server = self.config.plugin_config['server'] + + try: + self.port = int(self.config.plugin_config['port']) + except (AttributeError, ValueError): + self.port = 6667 + + self.nickname = self.config.plugin_config['bot_nickname'].encode("utf-8") + self.channel = self.config.plugin_config['channel'].encode("utf-8") + if 'nickserv_password' in self.config.plugin_config: + self.nickserv_password = self.config.plugin_config['nickserv_password'].encode("utf-8") + else: + self.nickserv_password = None + + self.echo_from_channel = self.config.plugin_config['echo_from_channel'] + + self.colors_with_irc_color = self.config.colors + self.colors_with_irc_color['irc'] = self.config.plugin_config['color'] + + if not getattr(self, 'irc_factory', None): + self.irc_factory = StarryPyIrcBotFactory(self.channel, self.logger, self.nickname, self.nickserv_password, self.factory, self.colors_with_irc_color, self.echo_from_channel) + self.irc_port = reactor.connectTCP(self.server, self.port, self.irc_factory) + + def deactivate(self): + if getattr(self, 'irc_manager', None): + self.irc_port.disconnect() + del self.irc_factory + + def on_chat_sent(self, data): + parsed = chat_sent().parse(data.data) + if not parsed.message.startswith('/'): + for p in self.irc_factory.irc_clients.itervalues(): + p.msg(self.channel, "<%s> %s" % (self.protocol.player.name.encode("utf-8"), parsed.message.encode("utf-8"))) + return True + + def on_client_connect(self, data): + parsed = client_connect().parse(data.data) + self.logger.info(parsed.name) + + for p in self.irc_factory.irc_clients.itervalues(): + p.msg(self.channel, "%s connected" % parsed.name.encode("utf-8")) + + return True + + def on_client_disconnect_request(self, data): + if self.protocol.player is not None: + for p in self.irc_factory.irc_clients.itervalues(): + p.msg(self.channel, "%s disconnected" % self.protocol.player.name.encode("utf-8")) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index d2db7f5..42012c7 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -1,7 +1,7 @@ # -*- coding: UTF-8 -*- from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels -from packets import warp_command_write, Packets, warp_command +from packets import player_warp_write, Packets, player_warp from utility_functions import build_packet, move_ship_to_coords, extract_name @@ -19,9 +19,9 @@ def activate(self): self.player_manager = self.plugins['player_manager'].player_manager ## Warp debugging - #def on_warp_command(self, data): + #def on_player_warp(self, data): # self.logger.debug("Warp packet: %s", data.data.encode('hex')) - # warp_data = warp_command().parse(data.data) + # warp_data = player_warp().parse(data.data) # self.logger.debug("Warp packet: %s", warp_data) @permissions(UserLevels.ADMIN) @@ -97,11 +97,11 @@ def warp_player_to_player(self, from_string, to_string): if from_player is not to_player: self.logger.debug("target: %s", to_player.uuid) warp_packet = build_packet(Packets.PLAYER_WARP, - warp_command_write(t="WARP_TO", + player_warp_write(t="WARP_TO", world_id=to_player.uuid)) else: warp_packet = build_packet(Packets.PLAYER_WARP, - warp_command_write(t="WARP_TO_OWN_SHIP", + player_warp_write(t="WARP_TO_OWN_SHIP", world_id=None)) from_protocol.client_protocol.transport.write(warp_packet) if from_string != to_string: @@ -170,7 +170,7 @@ def warp_player_to_outpost(self, player_string): if player_to_send is not None: player_protocol = self.factory.protocols[player_to_send.protocol] warp_packet = build_packet(Packets.PLAYER_WARP, - warp_command_write(t="WARP_TO", + player_warp_write(t="WARP_TO", world_id="outpost")) player_protocol.client_protocol.transport.write(warp_packet) self.protocol.send_chat_message("Warped ^yellow;%s^green; to the outpost." % player_string) diff --git a/server.py b/server.py index 9de9910..3d65519 100644 --- a/server.py +++ b/server.py @@ -64,59 +64,60 @@ def __init__(self): self.after_write_callback = None self.plugin_manager = None self.call_mapping = { - packets.Packets.PROTOCOL_VERSION: self.protocol_version, - packets.Packets.SERVER_DISCONNECT: self.server_disconnect, - packets.Packets.CONNECT_RESPONSE: self.connect_response, - packets.Packets.HANDSHAKE_CHALLENGE: self.handshake_challenge, - packets.Packets.CHAT_RECEIVED: self.chat_received, - packets.Packets.UNIVERSE_TIME_UPDATE: self.universe_time_update, - packets.Packets.CELESTIAL_RESPONSE: lambda x: True, - packets.Packets.CLIENT_CONNECT: self.client_connect, - packets.Packets.CLIENT_DISCONNECT_REQUEST: self.client_disconnect, - packets.Packets.HANDSHAKE_RESPONSE: self.handshake_response, - packets.Packets.PLAYER_WARP: self.warp_command, - packets.Packets.FLY_SHIP: lambda x: True, - packets.Packets.CHAT_SENT: self.chat_sent, - packets.Packets.CELESTIAL_REQUEST: self.celestial_request, - packets.Packets.CLIENT_CONTEXT_UPDATE: self.client_context_update, - packets.Packets.WORLD_START: self.world_start, - packets.Packets.WORLD_STOP: self.world_stop, - packets.Packets.CENTRAL_STRUCTURE_UPDATE: lambda x: True, - packets.Packets.TILE_ARRAY_UPDATE: self.tile_array_update, - packets.Packets.TILE_UPDATE: self.tile_update, - packets.Packets.TILE_LIQUID_UPDATE: self.tile_liquid_update, - packets.Packets.TILE_DAMAGE_UPDATE: self.tile_damage_update, - packets.Packets.TILE_MODIFICATION_FAILURE: self.tile_modification_failure, - packets.Packets.GIVE_ITEM: self.item, - packets.Packets.SWAP_IN_CONTAINER_RESULT: self.swap_in_container_result, - packets.Packets.ENVIRONMENT_UPDATE: self.environment_update, - packets.Packets.ENTITY_INTERACT_RESULT: self.entity_interact_result, - packets.Packets.UPDATE_TILE_PROTECTION: lambda x: True, - packets.Packets.MODIFY_TILE_LIST: self.modify_tile_list, - packets.Packets.DAMAGE_TILE_GROUP: self.damage_tile_group, - packets.Packets.COLLECT_LIQUID: lambda x: True, - packets.Packets.REQUEST_DROP: self.request_drop, - packets.Packets.SPAWN_ENTITY: self.spawn_entity, - packets.Packets.ENTITY_INTERACT: self.entity_interact, - packets.Packets.CONNECT_WIRE: self.connect_wire, - packets.Packets.DISCONNECT_ALL_WIRES: self.disconnect_all_wires, - packets.Packets.OPEN_CONTAINER: self.open_container, - packets.Packets.CLOSE_CONTAINER: self.close_container, - packets.Packets.SWAP_IN_CONTAINER: self.swap_in_container, - packets.Packets.ITEM_APPLY_IN_CONTAINER: self.item_apply_in_container, - packets.Packets.START_CRAFTING_IN_CONTAINER: self.start_crafting_in_container, - packets.Packets.STOP_CRAFTING_IN_CONTAINER: self.stop_crafting_in_container, - packets.Packets.BURN_CONTAINER: self.burn_container, - packets.Packets.CLEAR_CONTAINER: self.clear_container, - packets.Packets.WORLD_CLIENT_STATE_UPDATE: self.world_update, - packets.Packets.ENTITY_CREATE: self.entity_create, - packets.Packets.ENTITY_UPDATE: self.entity_update, - packets.Packets.ENTITY_DESTROY: self.entity_destroy, - packets.Packets.DAMAGE_REQUEST: lambda x: True, - packets.Packets.DAMAGE_NOTIFICATION: self.damage_notification, - packets.Packets.CALL_SCRIPTED_ENTITY: lambda x: True, - packets.Packets.UPDATE_WORLD_PROPERTIES: self.update_world_properties, - packets.Packets.HEARTBEAT: self.heartbeat, + packets.Packets.PROTOCOL_VERSION: self.protocol_version, # 0 + packets.Packets.SERVER_DISCONNECT: self.server_disconnect, # 1 + packets.Packets.CONNECT_RESPONSE: self.connect_response, # 2 + packets.Packets.HANDSHAKE_CHALLENGE: self.handshake_challenge, #3 + packets.Packets.CHAT_RECEIVED: self.chat_received, # 4 + packets.Packets.UNIVERSE_TIME_UPDATE: self.universe_time_update, # 5 + packets.Packets.CELESTIAL_RESPONSE: lambda x: True, # 6 + packets.Packets.CLIENT_CONNECT: self.client_connect, # 7 + packets.Packets.CLIENT_DISCONNECT_REQUEST: self.client_disconnect_request, # 8 + packets.Packets.HANDSHAKE_RESPONSE: self.handshake_response, # 9 + packets.Packets.PLAYER_WARP: self.player_warp, # 10 + packets.Packets.FLY_SHIP: lambda x: True, # 11 + packets.Packets.CHAT_SENT: self.chat_sent, # 12 + packets.Packets.CELESTIAL_REQUEST: self.celestial_request, # 13 + packets.Packets.CLIENT_CONTEXT_UPDATE: self.client_context_update, # 14 + packets.Packets.WORLD_START: self.world_start, # 15 + packets.Packets.WORLD_STOP: self.world_stop, # 16 + packets.Packets.CENTRAL_STRUCTURE_UPDATE: self.central_structure_update, # 17 + packets.Packets.TILE_ARRAY_UPDATE: self.tile_array_update, # 18 + packets.Packets.TILE_UPDATE: self.tile_update, # 19 + packets.Packets.TILE_LIQUID_UPDATE: self.tile_liquid_update, # 20 + packets.Packets.TILE_DAMAGE_UPDATE: self.tile_damage_update, # 21 + packets.Packets.TILE_MODIFICATION_FAILURE: self.tile_modification_failure, #22 + packets.Packets.GIVE_ITEM: self.give_item, # 23 + packets.Packets.SWAP_IN_CONTAINER_RESULT: self.swap_in_container_result, # 24 + packets.Packets.ENVIRONMENT_UPDATE: self.environment_update, # 25 + packets.Packets.ENTITY_INTERACT_RESULT: self.entity_interact_result, # 26 + packets.Packets.UPDATE_TILE_PROTECTION: lambda x: True, # 27 + packets.Packets.MODIFY_TILE_LIST: self.modify_tile_list, # 28 + packets.Packets.DAMAGE_TILE_GROUP: self.damage_tile_group, # 29 + packets.Packets.COLLECT_LIQUID: lambda x: True, # 30 + packets.Packets.REQUEST_DROP: self.request_drop, # 31 + packets.Packets.SPAWN_ENTITY: self.spawn_entity, # 32 + packets.Packets.ENTITY_INTERACT: self.entity_interact, # 33 + packets.Packets.CONNECT_WIRE: self.connect_wire, # 34 + packets.Packets.DISCONNECT_ALL_WIRES: self.disconnect_all_wires, # 35 + packets.Packets.OPEN_CONTAINER: self.open_container, # 36 + packets.Packets.CLOSE_CONTAINER: self.close_container, # 37 + packets.Packets.SWAP_IN_CONTAINER: self.swap_in_container, # 38 + packets.Packets.ITEM_APPLY_IN_CONTAINER: self.item_apply_in_container, # 39 + packets.Packets.START_CRAFTING_IN_CONTAINER: self.start_crafting_in_container, # 40 + packets.Packets.STOP_CRAFTING_IN_CONTAINER: self.stop_crafting_in_container, # 41 + packets.Packets.BURN_CONTAINER: self.burn_container, # 42 + packets.Packets.CLEAR_CONTAINER: self.clear_container, # 43 + packets.Packets.WORLD_CLIENT_STATE_UPDATE: self.world_client_state_update, # 44 + packets.Packets.ENTITY_CREATE: self.entity_create, # 45 + packets.Packets.ENTITY_UPDATE: self.entity_update, # 46 + packets.Packets.ENTITY_DESTROY: self.entity_destroy, # 47 + packets.Packets.HIT_REQUEST: lambda x: True, # 48 + packets.Packets.DAMAGE_REQUEST: lambda x: True, # 49 + packets.Packets.DAMAGE_NOTIFICATION: self.damage_notification, # 50 + packets.Packets.CALL_SCRIPTED_ENTITY: lambda x: True, # 51 + packets.Packets.UPDATE_WORLD_PROPERTIES: self.update_world_properties, # 52 + packets.Packets.HEARTBEAT: self.heartbeat, # 53 } self.client_protocol = None self.packet_stream = PacketStream(self) @@ -217,6 +218,10 @@ def world_start(self, data): def world_stop(self, data): return True + @route + def central_structure_update(self, data): + return True + @route def tile_array_update(self, data): return True @@ -238,7 +243,7 @@ def tile_modification_failure(self, data): return True @route - def item(self, data): + def give_item(self, data): return True @route @@ -318,7 +323,7 @@ def clear_container(self, data): return True @route - def world_update(self, data): + def world_client_state_update(self, data): return True @route @@ -392,7 +397,7 @@ def client_connect(self, data): return True @route - def client_disconnect(self, player): + def client_disconnect_request(self, player): """ Called when the client signals that it is about to disconnect from the Starbound server. @@ -402,11 +407,11 @@ def client_disconnect(self, player): return True @route - def warp_command(self, data): + def player_warp(self, data): """ Called when the players issues a warp. - :param data: The warp_command data. + :param data: The player_warp data. :rtype : bool """ return True @@ -467,9 +472,9 @@ def connectionLost(self, reason=connectionDone): try: if self.client_protocol is not None: x = build_packet(packets.Packets.CLIENT_DISCONNECT_REQUEST, - packets.client_disconnect().build(Container(data=0))) + packets.client_disconnect_request().build(Container(data=0))) if self.player is not None and self.player.logged_in: - self.client_disconnect(x) + self.client_disconnect_request(x) self.client_protocol.transport.write(x) self.client_protocol.transport.abortConnection() except: @@ -548,7 +553,7 @@ def dataReceived(self, data): self.packet_stream += data def disconnect(self): - x = build_packet(packets.Packets.CLIENT_DISCONNECT_REQUEST, packets.client_disconnect().build(Container(data=0))) + x = build_packet(packets.Packets.CLIENT_DISCONNECT_REQUEST, packets.client_disconnect_request().build(Container(data=0))) self.transport.write(x) self.transport.abortConnection() diff --git a/utility_functions.py b/utility_functions.py index a8eb265..c57a524 100644 --- a/utility_functions.py +++ b/utility_functions.py @@ -64,8 +64,8 @@ def move_ship_to_coords(protocol, x, y, z, planet, satellite): logger.info("Moving %s's ship to coordinates: %s", protocol.player.name, ":".join((str(x), str(y), str(z), str(planet), str(satellite)))) x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) - warp_packet = build_packet(packets.Packets.WARP_COMMAND, - packets.warp_command_write(t="WARP_TO", x=x, y=y, z=z, + warp_packet = build_packet(packets.Packets.PLAYER_WARP, + packets.player_warp_write(t="WARP_TO", x=x, y=y, z=z, planet=planet, satellite=satellite, player="".encode('utf-8'))) protocol.client_protocol.transport.write(warp_packet) From 1c8e1959e1ef0022805d7c83ee9ab8e374cc5ae7 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sun, 1 Feb 2015 23:24:08 -0500 Subject: [PATCH 59/95] changed some permissions on warpy --- plugins/warpy_plugin/warpy_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 42012c7..7926b2f 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -24,7 +24,7 @@ def activate(self): # warp_data = player_warp().parse(data.data) # self.logger.debug("Warp packet: %s", warp_data) - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def warp(self, name): """Warps you to a player's ship (or player to player).\nSyntax: /warp [player] (to player)""" if len(name) == 0: @@ -68,7 +68,7 @@ def warp_ship(self, location): self.move_player_ship_to_other(first_name, second_name) #!!!!!!!!!!!!!!!!!!!!!!! - @permissions(UserLevels.ADMIN) + @permissions(UserLevels.MODERATOR) def outpost(self, name): """Warps you (or another player) to the outpost.\nSyntax: /outpost [player]""" if len(name) == 0: From ef9d969a37bf4913b56436bcea5d5213ae22d2ad Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Mon, 2 Feb 2015 03:31:53 -0500 Subject: [PATCH 60/95] split bookmarks into two plugins (bookmarks and poi). Moved spawn command out of command dispatecher, and into warpy. Ship warping still DOES NOT WORK. Packet parsing issues remain to be sorted out. --- .../a87d5e4bfa6fabc4deea7ddd50fb6e99.json | 1 + config/pois.json | 1 + plugins/bookmarks_plugin/__init__.py | 1 + plugins/bookmarks_plugin/bookmarks_plugin.py | 156 ++++++++++++++++++ .../starbound_config_manager.py | 16 +- plugins/poi_plugin/__init__.py | 1 + plugins/poi_plugin/poi_plugin.py | 117 +++++++++++++ plugins/warpy_plugin/warpy_plugin.py | 11 +- 8 files changed, 288 insertions(+), 16 deletions(-) create mode 100644 config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json create mode 100644 config/pois.json create mode 100644 plugins/bookmarks_plugin/__init__.py create mode 100644 plugins/bookmarks_plugin/bookmarks_plugin.py create mode 100644 plugins/poi_plugin/__init__.py create mode 100644 plugins/poi_plugin/poi_plugin.py diff --git a/config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json b/config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json new file mode 100644 index 0000000..afec3fd --- /dev/null +++ b/config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json @@ -0,0 +1 @@ +[["-30562840:658406569:-263745435:4:0", "forest"], ["-30562840:658406569:-263745435:3:6", "spawn"]] \ No newline at end of file diff --git a/config/pois.json b/config/pois.json new file mode 100644 index 0000000..39d1633 --- /dev/null +++ b/config/pois.json @@ -0,0 +1 @@ +[["-30562840:658406569:-263745435:3:6", "spawn"], ["-30562840:658406569:-263745435:4:0", "forest"]] \ No newline at end of file diff --git a/plugins/bookmarks_plugin/__init__.py b/plugins/bookmarks_plugin/__init__.py new file mode 100644 index 0000000..1c97db5 --- /dev/null +++ b/plugins/bookmarks_plugin/__init__.py @@ -0,0 +1 @@ +from bookmarks_plugin import Bookmarks \ No newline at end of file diff --git a/plugins/bookmarks_plugin/bookmarks_plugin.py b/plugins/bookmarks_plugin/bookmarks_plugin.py new file mode 100644 index 0000000..83ad309 --- /dev/null +++ b/plugins/bookmarks_plugin/bookmarks_plugin.py @@ -0,0 +1,156 @@ +import os +import errno +import json +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +from packets import player_warp_write, Packets +from utility_functions import build_packet + + +class Bookmarks(SimpleCommandPlugin): + """ + Plugin that allows defining planets as personal bookmarks you can /goto to. + """ + name = "bookmarks_plugin" + depends = ['command_dispatcher', 'player_manager'] + commands = ["bookmark", "remove", "goto"] + auto_activate = True + + def activate(self): + super(Bookmarks, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + self.verify_path("./config/bookmarks") + + @permissions(UserLevels.GUEST) + def bookmark(self, name): + """Bookmarks a planet for fast warp routes.\nSyntax: /bookmark (name)""" + filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" + try: + with open(filename) as f: + self.bookmarks = json.load(f) + except: + self.bookmarks = [] + + name = " ".join(name).strip().strip("\t") + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + + if on_ship: + self.protocol.send_chat_message("You need to be on a planet!") + return + if len(name) == 0: + warps = [] + for warp in self.bookmarks: + if warps != "": + warps.append(warp[1]) + warpnames = "^green;,^yellow; ".join(warps) + if warpnames == "": warpnames = "^gray;(none)^green;" + self.protocol.send_chat_message(self.bookmark.__doc__) + self.protocol.send_chat_message("Please, provide a valid bookmark name!\nBookmarks: ^yellow;" + warpnames) + return + + for warp in self.bookmarks: + if warp[0] == planet: + self.protocol.send_chat_message("The planet you're on is already bookmarked: ^yellow;" + warp[1]) + return + if warp[1] == name: + self.protocol.send_chat_message("Bookmark with that name already exists!") + return + self.bookmarks.append([planet, name]) + self.protocol.send_chat_message("Bookmark ^yellow;%s^green; added." % name) + self.savebms() + + @permissions(UserLevels.GUEST) + def remove(self, name): + """Removes current planet from bookmarks.\nSyntax: /remove (name)""" + filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" + try: + with open(filename) as f: + self.bookmarks = json.load(f) + except: + self.bookmarks = [] + name = " ".join(name).strip().strip("\t") + if len(name) == 0: + warps = [] + for warp in self.bookmarks: + if warps != "": + warps.append(warp[1]) + warpnames = "^green;,^yellow; ".join(warps) + if warpnames == "": warpnames = "^gray;(none)^green;" + self.protocol.send_chat_message(self.remove.__doc__) + self.protocol.send_chat_message("Please, provide a valid bookmark name!\nBookmarks: ^yellow;" + warpnames) + return + + for warp in self.bookmarks: + if warp[1] == name: + self.bookmarks.remove(warp) + self.protocol.send_chat_message("Bookmark ^yellow;%s^green; removed." % name) + self.savebms() + return + self.protocol.send_chat_message("There is no bookmark named: ^yellow;%s" % name) + + @permissions(UserLevels.GUEST) + def goto(self, name): + """Warps your ship to a previously bookmarked planet.\nSyntax: /goto [name] *omit name for a list of bookmarks""" + filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" + try: + with open(filename) as f: + self.bookmarks = json.load(f) + except: + self.bookmarks = [] + name = " ".join(name).strip().strip("\t") + if len(name) == 0: + warps = [] + for warp in self.bookmarks: + if warps != "": + warps.append(warp[1]) + warpnames = "^green;,^yellow; ".join(warps) + if warpnames == "": warpnames = "^gray;(none)^green;" + self.protocol.send_chat_message(self.goto.__doc__) + self.protocol.send_chat_message("Bookmarks: ^yellow;" + warpnames) + return + + on_ship = self.protocol.player.on_ship + if not on_ship: + self.protocol.send_chat_message("You need to be on a ship!") + return + + for warp in self.bookmarks: + if warp[1] == name: + x, y, z, planet, satellite = warp[0].split(":") + x, y, z, planet, satellite = map((x, y, z, planet, satellite)) + warp_packet = build_packet(Packets.PLAYER_WARP, + player_warp_write(t="WARP_TO", + x=x, + y=y, + z=z, + planet=planet, + satellite=satellite)) + self.protocol.client_protocol.transport.write(warp_packet) + self.protocol.send_chat_message("Warp drive engaged! Warping to ^yellow;%s^green;." % name) + return + self.protocol.send_chat_message("There is no bookmark named: ^yellow;%s" % name) + + def verify_path(self, path): + try: + os.makedirs(path) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + + def savebms(self): + filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" + try: + with open(filename, "w") as f: + json.dump(self.bookmarks, f) + except: + self.logger.exception("Couldn't save bookmarks.") + raise + + def beam_to_planet(self, where): + warp_packet = build_packet(Packets.PLAYER_WARP, player_warp_write(t="WARP_DOWN")) + self.protocol.client_protocol.transport.write(warp_packet) + self.protocol.send_chat_message("Beamed down to ^yellow;%s^green; and your ship will arrive soon." % where) + self.factory.broadcast_planet( + "%s^green; beamed down to the planet" % self.protocol.player.colored_name(self.config.colors), + planet=self.protocol.player.planet) diff --git a/plugins/core/starbound_config_manager/starbound_config_manager.py b/plugins/core/starbound_config_manager/starbound_config_manager.py index b82a2a2..3c4e6eb 100644 --- a/plugins/core/starbound_config_manager/starbound_config_manager.py +++ b/plugins/core/starbound_config_manager/starbound_config_manager.py @@ -2,13 +2,11 @@ from twisted.python.filepath import FilePath from base_plugin import SimpleCommandPlugin from plugin_manager import FatalPluginError -from plugins.core import permissions, UserLevels class StarboundConfigManager(SimpleCommandPlugin): name = "starbound_config_manager" - depends = ['command_dispatcher', 'warpy_plugin'] - commands = ["spawn"] + depends = ['command_dispatcher'] def activate(self): super(StarboundConfigManager, self).activate() @@ -30,15 +28,3 @@ def activate(self): raise FatalPluginError( "The starbound gameServerPort option (%d) does not match the config.json upstream_port (%d)." % ( starbound_config['gameServerPort'], self.config.upstream_port)) - #self._spawn = starbound_config['defaultWorldCoordinate'].split(":") - self._spawn = "junk" - - @permissions(UserLevels.GUEST) - def spawn(self, data): - """Warps your ship to spawn.\nSyntax: /spawn""" - on_ship = self.protocol.player.on_ship - if not on_ship: - self.protocol.send_chat_message("You need to be on a ship!") - return - self.plugins['warpy_plugin'].move_player_ship(self.protocol, [x for x in self._spawn]) - self.protocol.send_chat_message("Moving your ship to spawn.") diff --git a/plugins/poi_plugin/__init__.py b/plugins/poi_plugin/__init__.py new file mode 100644 index 0000000..766075f --- /dev/null +++ b/plugins/poi_plugin/__init__.py @@ -0,0 +1 @@ +from poi_plugin import PointsofInterest diff --git a/plugins/poi_plugin/poi_plugin.py b/plugins/poi_plugin/poi_plugin.py new file mode 100644 index 0000000..7c4a817 --- /dev/null +++ b/plugins/poi_plugin/poi_plugin.py @@ -0,0 +1,117 @@ +import json +#from twisted.internet import reactor +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +from packets import player_warp_write, Packets +from utility_functions import build_packet + + +class PointsofInterest(SimpleCommandPlugin): + """ + Plugin that allows admins to define Planets of Interest (PoI) any player can /poi to. + """ + name = "poi_plugin" + depends = ['command_dispatcher', 'player_manager'] + commands = ["poi_set", "poi_del", "poi"] + auto_activate = True + + def activate(self): + super(PointsofInterest, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + try: + with open("./config/pois.json") as f: + self.pois = json.load(f) + except: + self.pois = [] + + # Commands that allows admins to define Planets of Interest (PoI) any player can /poi to. + @permissions(UserLevels.ADMIN) + def poi_set(self, name): + """Sets current planet as Planet of Interest (PoI).\nSyntax: /poi_set (name)""" + name = " ".join(name).strip().strip("\t") + if len(name) == 0: + self.protocol.send_chat_message(self.poi_set.__doc__) + return + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + if on_ship: + self.protocol.send_chat_message("You need to be on a planet!") + return + for warp in self.pois: + if warp[0] == planet: + self.protocol.send_chat_message("The planet you're on is already set as a PoI: ^yellow;" + warp[1]) + return + if warp[1] == name: + self.protocol.send_chat_message("Planet of Interest named ^yellow;%s^green; already exists." % name) + return + self.pois.append([planet, name]) + self.protocol.send_chat_message("Planet of Interest ^yellow;%s^green; added." % name) + self.savepois() + + @permissions(UserLevels.ADMIN) + def poi_del(self, name): + """Removes current planet as Planet of Interest (PoI).\nSyntax: /poi_del (name)""" + name = " ".join(name).strip().strip("\t") + if len(name) == 0: + self.protocol.send_chat_message(self.poi_del.__doc__) + return + for warp in self.pois: + if warp[1] == name: + self.pois.remove(warp) + self.protocol.send_chat_message("Planet of Interest ^yellow;%s^green; removed." % name) + self.savepois() + return + self.protocol.send_chat_message("There is no PoI named: ^yellow;%s^green;." % name) + + @permissions(UserLevels.GUEST) + def poi(self, name): + """Warps your ship to a Planet of Interest (PoI).\nSyntax: /poi [name] *omit name for a list of PoI's""" + name = " ".join(name).strip().strip("\t") + if len(name) == 0: + warps = [] + for warp in self.pois: + if warps != "": + warps.append(warp[1]) + warpnames = "^green;, ^yellow;".join(warps) + if warpnames == "": warpnames = "^gray;(none)^green;" + self.protocol.send_chat_message(self.poi.__doc__) + self.protocol.send_chat_message("List of PoI's: ^yellow;" + warpnames) + return + + on_ship = self.protocol.player.on_ship + if not on_ship: + self.protocol.send_chat_message("You need to be on a ship!") + return + + for warp in self.pois: + if warp[1] == name: + x, y, z, planet, satellite = warp[0].split(":") + x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) + warp_packet = build_packet(Packets.PLAYER_WARP, + player_warp_write(t="WARP_TO", + x=x, + y=y, + z=z, + planet=planet, + satellite=satellite)) + self.protocol.client_protocol.transport.write(warp_packet) + self.protocol.send_chat_message("Warp drive engaged! Warping to ^yellow;%s^green;." % name) + #reactor.callLater(1, self.beam_to_planet, name) # enable this for 1s delayed warping of a player + return + self.protocol.send_chat_message("There is no PoI named ^yellow;%s^green;." % name) + + def savepois(self): + try: + with open("./config/pois.json", "w") as f: + json.dump(self.pois, f) + except: + self.logger.exception("Couldn't save PoI's.") + raise + + def beam_to_planet(self, where): + warp_packet = build_packet(Packets.PLAYER_WARP, player_warp_write(t="WARP_DOWN")) + self.protocol.client_protocol.transport.write(warp_packet) + self.protocol.send_chat_message("Beamed down to ^yellow;%s^green; and your ship will arrive soon." % where) + self.factory.broadcast_planet( + "%s^green; beamed down to the planet" % self.protocol.player.colored_name(self.config.colors), + planet=self.protocol.player.planet) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 7926b2f..1b18a15 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -11,7 +11,7 @@ class Warpy(SimpleCommandPlugin): """ name = "warpy_plugin" depends = ['command_dispatcher', 'player_manager'] - commands = ["warp", "warp_ship", "outpost"] + commands = ["warp", "warp_ship", "outpost", "spawn"] auto_activate = True def activate(self): @@ -178,3 +178,12 @@ def warp_player_to_outpost(self, player_string): self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % player_string) self.protocol.send_chat_message(self.warp.__doc__) + @permissions(UserLevels.GUEST) + def spawn(self, data): + """Warps your ship to spawn.\nSyntax: /spawn""" + on_ship = self.protocol.player.on_ship + if not on_ship: + self.protocol.send_chat_message("You need to be on a ship!") + return + self.plugins['warpy_plugin'].move_player_ship(self.protocol, [x for x in self._spawn]) + self.protocol.send_chat_message("Moving your ship to spawn.") From 3a24e87725e11272ccc948ff0ac96ccffc8bc8aa Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Mon, 2 Feb 2015 11:59:18 -0500 Subject: [PATCH 61/95] Fixed the default.json file to work out of the box correctly (no more bugging out over) --- config/config.json.default | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index a61db7d..f4194c5 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -7,6 +7,7 @@ "admin": "^#C443F7;", "default": "^#F7EB43;", "guest": "^#F7EB43;", + "irc": "^#e39313;", "moderator": "^#4385F7;", "owner": "^#F7434C;", "registered": "^#A0F743;" @@ -27,12 +28,28 @@ "announcer_plugin": { "auto_activate": true }, + "bookmarks_plugin": { + "auto_activate": true + }, "chat_logger": { "auto_activate": true }, + "colored_names_plugin": { + "auto_activate": true + }, "command_dispatcher": { "auto_activate": true }, + "irc": { + "auto_activate": true, + "bot_nickname": "StarryPyBot", + "channel": "##test", + "color": "^#e39313;", + "echo_from_channel": true, + "nickserv_password": "password", + "port": 6667, + "server": "irc.freenode.net" + }, "motd_plugin": { "auto_activate": true, "motd": "Welcome to the server! Play nice." @@ -46,10 +63,6 @@ [ "coalore", 200 - ], - [ - "alienburger", - 5 ] ], "message": "Welcome to the server!" @@ -65,11 +78,6 @@ "DAMAGE_TILE_GROUP", "MODIFY_TILE_LIST" ], - "bad_packets_ship": [ - "ENTITY_INTERACT", - "OPEN_CONTAINER", - "CLOSE_CONTAINER" - ], "bad_packets_mild": [ "CONNECT_WIRE", "DISCONNECT_ALL_WIRES", @@ -77,6 +85,11 @@ "DAMAGE_TILE_GROUP", "MODIFY_TILE_LIST" ], + "bad_packets_ship": [ + "ENTITY_INTERACT", + "OPEN_CONTAINER", + "CLOSE_CONTAINER" + ], "blacklist": [ "bomb", "bombblockexplosion", @@ -161,9 +174,15 @@ "[^ \\w]+" ] }, + "players_plugin": { + "auto_activate": true + }, "plugin_manager": { "auto_activate": true }, + "poi_plugin": { + "auto_activate": true + }, "starbound_config_manager": { "auto_activate": true }, From 083cc04510230c3aebaadc1102f466f1f15d8236 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Mon, 2 Feb 2015 12:21:46 -0500 Subject: [PATCH 62/95] Turned IRC auto_enable off in config.json.defualts --- config/config.json.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json.default b/config/config.json.default index f4194c5..518289a 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -41,7 +41,7 @@ "auto_activate": true }, "irc": { - "auto_activate": true, + "auto_activate": false, "bot_nickname": "StarryPyBot", "channel": "##test", "color": "^#e39313;", From 88dbf6dd7cd74a0ed895a0ee7ea7c31067a64867 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Mon, 2 Feb 2015 20:01:37 -0500 Subject: [PATCH 63/95] Made some changes to logging. I removed the extra logging-level that was put in (TRACE), and instead pushed everything onto DEBUG. In addition, I modified the default options the live in the config.json file. My reasoning is that, logging was somewhat confusing, and the way it was setup carried more options than were needed. Instead, the server-owner need-only choose their logging-level from the config file, and run the server. In turn, the server now pushes all logging information into one central log-file, to reduce redundancy. I will likely add another log level back in for packet-dumping, since that is sometimes more than what debug needs as well. --- __init__.py | 6 - base_plugin.py | 6 + config/config.json.default | 5 +- packet_stream.py | 13 +-- packets/packet_types.py | 17 +-- .../admin_command_plugin.py | 32 +++--- plugins/core/player_manager/manager.py | 10 +- plugins/poi_plugin/poi_plugin.py | 5 +- server.py | 105 +++++++++--------- 9 files changed, 102 insertions(+), 97 deletions(-) diff --git a/__init__.py b/__init__.py index 6b163a6..ade1461 100644 --- a/__init__.py +++ b/__init__.py @@ -1,7 +1 @@ import logging -TRACE_LVL = 9 -logging.addLevelName(TRACE_LVL, "TRACE") - -def trace(self, message, *args, **kws): - self._log(TRACE_LVL, message, args, **kws) -logging.Logger.trace = trace \ No newline at end of file diff --git a/base_plugin.py b/base_plugin.py index f15d210..4cbd2bf 100644 --- a/base_plugin.py +++ b/base_plugin.py @@ -188,6 +188,9 @@ def on_client_disconnect_request(self, player): def on_player_warp(self, data): return True + def on_fly_ship(self, data): + return True + def on_central_structure_update(self, data): return True @@ -335,6 +338,9 @@ def after_client_disconnect_request(self, data): def after_player_warp(self, data): return True + def after_fly_ship(self, data): + return True + def after_central_structure_update(self, data): return True diff --git a/config/config.json.default b/config/config.json.default index 518289a..934e18b 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -14,10 +14,7 @@ }, "command_prefix": "/", "core_plugin_path": "core_plugins", - "debug_file": "debug.log", - "logging_format_console": "%(asctime)s - %(name)s - %(levelname)s - %(message)s", - "logging_format_debugfile": "%(asctime)s - %(name)s - %(levelname)s - %(message)s", - "logging_format_logfile": "%(asctime)s - %(name)s - %(levelname)s - %(message)s", + "log_level": "DEBUG", "owner_uuid": "!!--REPLACE THIS--!!", "passthrough": false, "player_db": "config/player.db", diff --git a/packet_stream.py b/packet_stream.py index 979704b..9ea81e6 100644 --- a/packet_stream.py +++ b/packet_stream.py @@ -71,14 +71,13 @@ def check_packet(self): z = zlib.decompressobj() p_parsed.data = z.decompress(p_parsed.data) except zlib.error: - self.logger.error("Decompression error in check_packet.") - self.logger.trace("Parsed packet:") - self.logger.trace(pprint.pformat(p_parsed)) - self.logger.trace("Packet data:") - self.logger.trace(pprint.pformat(p_parsed.original_data.encode("hex"))) - self.logger.trace("Following packet data:") - self.logger.trace(pprint.pformat(self._stream.encode("hex"))) + self.logger.debug("Parsed packet:") + self.logger.debug(pprint.pformat(p_parsed)) + self.logger.debug("Packet data:") + self.logger.debug(pprint.pformat(p_parsed.original_data.encode("hex"))) + self.logger.debug("Following packet data:") + self.logger.debug(pprint.pformat(self._stream.encode("hex"))) raise packet = Packet(packet_id=p_parsed.id, payload_size=p_parsed.payload_size, data=p_parsed.data, original_data=p, direction=self.direction) diff --git a/packets/packet_types.py b/packets/packet_types.py index 4ae9bd7..0ea1ed6 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -181,12 +181,12 @@ def _decode(self, obj, context): celestial_request = lambda name="celestial_request": Struct(name, GreedyRange(star_string("requests"))) -world_coordinate = lambda name="world_coordinate": Struct(name, - SBInt32("x"), - SBInt32("y"), - SBInt32("z"), - SBInt32("planet"), - SBInt32("satellite")) +celestial_coordinate = lambda name="celestial_coordinate": Struct(name, + SBInt32("x"), + SBInt32("y"), + SBInt32("z"), + SBInt32("planet"), + SBInt32("satellite")) player_warp = lambda name="player_warp": Struct(name, Enum(UBInt8("warp_type"), @@ -202,6 +202,8 @@ def _decode(self, obj, context): warp_type=t, world_id=world_id)) +fly_ship = lambda name="fly_ship": Struct(name, + celestial_coordinate()) # partially correct. Needs work on dungeon ID value world_start = lambda name="world_start": Struct(name, @@ -209,7 +211,8 @@ def _decode(self, obj, context): StarByteArray("sky_data"), StarByteArray("weather_data"), #dungeon id stuff here - Array(2, BFloat32("coordinate")), + BFloat32("x"), + BFloat32("y"), Variant("world_properties"), UBInt32("client_id"), Flag("local_interpolation")) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index d2a9afe..12174f1 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -70,18 +70,18 @@ def whois(self, data): @permissions(UserLevels.MODERATOR) def promote(self, data): """Promotes/demotes a player to a specific rank.\nSyntax: /promote (player) (rank) (where rank is either: guest, registered, moderator, admin, or owner)""" - self.logger.trace("Promote command received with the following data: %s" % ":".join(data)) + self.logger.debug("Promote command received with the following data: %s" % ":".join(data)) if len(data) > 0: name = " ".join(data[:-1]) - self.logger.trace("Extracted the name %s in promote command." % name) + self.logger.debug("Extracted the name %s in promote command." % name) rank = data[-1].lower() - self.logger.trace("Extracted the rank %s in the promote command." % rank) + self.logger.debug("Extracted the rank %s in the promote command." % rank) player = self.player_manager.get_by_name(name) - self.logger.trace("Player object in promote command, found by name, is %s." % str(player)) + self.logger.debug("Player object in promote command, found by name, is %s." % str(player)) if player is not None: - self.logger.trace("Player object was not None. Dump of player object follows.") + self.logger.debug("Player object was not None. Dump of player object follows.") for line in pprint.pformat(player).split("\n"): - self.logger.trace("\t" + line) + self.logger.debug("\t" + line) old_rank = player.access_level players = self.player_manager.all() if old_rank == 1000: @@ -93,7 +93,7 @@ def promote(self, data): self.protocol.send_chat_message("You are the only (or last) owner. Promote denied!") return if old_rank >= self.protocol.player.access_level and not self.protocol.player.access_level != UserLevels.ADMIN: - self.logger.trace( + self.logger.debug( "The old rank was greater or equal to the current rank. Sending a message and returning.") self.protocol.send_chat_message( "You cannot change that user's access level as they are at least at an equal level as you.") @@ -109,15 +109,15 @@ def promote(self, data): elif rank == "guest": self.make_guest(player) else: - self.logger.trace("Non-existent rank. Returning with a help message.") + self.logger.debug("Non-existent rank. Returning with a help message.") self.protocol.send_chat_message("No such rank!\n" + self.promote.__doc__) return - self.logger.trace("Sending promotion message to promoter.") + self.logger.debug("Sending promotion message to promoter.") self.protocol.send_chat_message("%s: %s -> %s" % ( player.colored_name(self.config.colors), UserLevels(old_rank), rank.upper())) - self.logger.trace("Sending promotion message to promoted player.") + self.logger.debug("Sending promotion message to promoted player.") try: self.factory.protocols[player.protocol].send_chat_message( "%s has promoted you to %s" % ( @@ -125,31 +125,31 @@ def promote(self, data): except KeyError: self.logger.info("Promoted player is not logged in.") else: - self.logger.trace("Player wasn't found. Sending chat message to player.") + self.logger.debug("Player wasn't found. Sending chat message to player.") self.protocol.send_chat_message("Player not found!\n" + self.promote.__doc__) return else: - self.logger.trace("Received blank promotion command. Sending help message.") + self.logger.debug("Received blank promotion command. Sending help message.") self.protocol.send_chat_message(self.promote.__doc__) @permissions(UserLevels.MODERATOR) def make_guest(self, player): - self.logger.trace("Setting %s to GUEST", player.name) + self.logger.debug("Setting %s to GUEST", player.name) player.access_level = UserLevels.GUEST @permissions(UserLevels.MODERATOR) def make_registered(self, player): - self.logger.trace("Setting %s to REGISTERED", player.name) + self.logger.debug("Setting %s to REGISTERED", player.name) player.access_level = UserLevels.REGISTERED @permissions(UserLevels.ADMIN) def make_mod(self, player): player.access_level = UserLevels.MODERATOR - self.logger.trace("Setting %s to MODERATOR", player.name) + self.logger.debug("Setting %s to MODERATOR", player.name) @permissions(UserLevels.OWNER) def make_admin(self, player): - self.logger.trace("Setting %s to ADMIN", player.name) + self.logger.debug("Setting %s to ADMIN", player.name) player.access_level = UserLevels.ADMIN @permissions(UserLevels.OWNER) diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index 11127e7..a510ec1 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -162,13 +162,13 @@ class Player(Base): ips = relationship("IPAddress", order_by="IPAddress.id", backref="players") def colored_name(self, colors): - logger.trace("Building colored name.") + logger.debug("Building colored name.") color = colors[UserLevels(self.access_level).lower()] - logger.trace("Color is %s", color) + logger.debug("Color is %s", color) name = self.name - logger.trace("Name is %s", name) - logger.trace("Returning the following data for colored name. %s:%s:%s", color, name, - colors['default']) + logger.debug("Name is %s", name) + logger.debug("Returning the following data for colored name. %s:%s:%s", + color, name, colors['default']) return color + name + colors["default"] @property diff --git a/plugins/poi_plugin/poi_plugin.py b/plugins/poi_plugin/poi_plugin.py index 7c4a817..7ed195f 100644 --- a/plugins/poi_plugin/poi_plugin.py +++ b/plugins/poi_plugin/poi_plugin.py @@ -2,7 +2,7 @@ #from twisted.internet import reactor from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels -from packets import player_warp_write, Packets +from packets import player_warp_write, Packets, fly_ship from utility_functions import build_packet @@ -15,6 +15,9 @@ class PointsofInterest(SimpleCommandPlugin): commands = ["poi_set", "poi_del", "poi"] auto_activate = True + def after_fly_ship(self, data): + self.logger.debug("Coords: %s", fly_ship().parse(data.data)) + def activate(self): super(PointsofInterest, self).activate() self.player_manager = self.plugins['player_manager'].player_manager diff --git a/server.py b/server.py index 3d65519..0cd0f46 100644 --- a/server.py +++ b/server.py @@ -1,6 +1,6 @@ # -*- coding: UTF-8 -*- from _socket import SHUT_RDWR -import gettext +#import gettext import locale import logging from uuid import uuid4 @@ -8,13 +8,12 @@ import socket import datetime -import construct from twisted.internet import reactor from twisted.internet.error import CannotListenError from twisted.internet.protocol import ClientFactory, ServerFactory, Protocol, connectionDone +from twisted.internet.task import LoopingCall from construct import Container import construct.core -from twisted.internet.task import LoopingCall from config import ConfigurationManager from packet_stream import PacketStream @@ -23,10 +22,6 @@ from utility_functions import build_packet VERSION = "1.4.4" -TRACE = False -TRACE_LVL = 9 -logging.addLevelName(9, "TRACE") -logging.Logger.trace = lambda s, m, *a, **k: s._log(TRACE_LVL, m, a, **k) def port_check(upstream_hostname, upstream_port): @@ -53,11 +48,11 @@ def __init__(self): """ """ self.id = str(uuid4().hex) - logger.trace("Creating protocol with ID %s.", self.id) + logger.debug("Creating protocol with ID %s.", self.id) self.factory.protocols[self.id] = self self.player = None self.state = None - logger.trace("Trying to initialize configuration manager.") + logger.debug("Trying to initialize configuration manager.") self.config = ConfigurationManager() self.parsing = False self.buffering_packet = None @@ -75,7 +70,7 @@ def __init__(self): packets.Packets.CLIENT_DISCONNECT_REQUEST: self.client_disconnect_request, # 8 packets.Packets.HANDSHAKE_RESPONSE: self.handshake_response, # 9 packets.Packets.PLAYER_WARP: self.player_warp, # 10 - packets.Packets.FLY_SHIP: lambda x: True, # 11 + packets.Packets.FLY_SHIP: self.fly_ship, # 11 packets.Packets.CHAT_SENT: self.chat_sent, # 12 packets.Packets.CELESTIAL_REQUEST: self.celestial_request, # 13 packets.Packets.CLIENT_CONTEXT_UPDATE: self.client_context_update, # 14 @@ -416,6 +411,16 @@ def player_warp(self, data): """ return True + @route + def fly_ship(self, data): + """ + Called when the players moves their ship. + + :param data: The fly_ship data. + :rtype : bool + """ + return True + def handle_starbound_packets(self, p): """ This function is the meat of it all. Every time a full packet with @@ -442,16 +447,18 @@ def send_chat_message(self, text, mode=0, channel='', name=''): self.send_chat_message(line) return if self.player is not None: - logger.trace("Calling send_chat_message from player %s on channel %d with mode %d with reported username of %s with message: %s", self.player.name, channel, mode, name, text) + logger.debug(('Calling send_chat_message from player %s on channel' + ' %s with mode %s with reported username of %s with' + ' message: %s'), self.player.name, channel, mode, name, text) chat_data = packets.chat_received().build(Container(mode=mode, chat_channel=channel, client_id=0, name=name, message=text.encode("utf-8"))) - logger.trace("Built chat payload. Data: %s", chat_data.encode("hex")) + logger.debug("Built chat payload. Data: %s", chat_data.encode("hex")) chat_packet = build_packet(packets.Packets.CHAT_RECEIVED, chat_data) - logger.trace("Built chat packet. Data: %s", chat_packet.encode("hex")) + logger.debug("Built chat packet. Data: %s", chat_packet.encode("hex")) self.transport.write(chat_packet) logger.debug("Sent chat message with text: %s", text) @@ -638,13 +645,13 @@ def reap_dead_protocols(self): start_time = datetime.datetime.now() for protocol in self.protocols.itervalues(): if (protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: - logger.trace("Reaping protocol %s. Reason: Server protocol timeout.", protocol.id) + logger.debug("Reaping protocol %s. Reason: Server protocol timeout.", protocol.id) protocol.connectionLost() count += 1 continue if protocol.client_protocol is not None and (protocol.client_protocol.packet_stream.last_received_timestamp - start_time).total_seconds() > self.config.reap_time: protocol.connectionLost() - logger.trace("Reaping protocol %s. Reason: Client protocol timeout.", protocol.id) + logger.debug("Reaping protocol %s. Reason: Client protocol timeout.", protocol.id) count += 1 if count == 1: logger.info("1 connection reaped.") @@ -661,11 +668,11 @@ class StarboundClientFactory(ClientFactory): protocol = ClientProtocol def __init__(self, server_protocol): - logger.trace("Client protocol instantiated.") + logger.debug("Client protocol instantiated.") self.server_protocol = server_protocol def buildProtocol(self, address): - logger.trace("Building protocol in StarboundClientFactory to address %s", address) + logger.debug("Building protocol in StarboundClientFactory to address %s", address) protocol = ClientFactory.buildProtocol(self, address) protocol.server_protocol = self.server_protocol return protocol @@ -674,46 +681,42 @@ def init_localization(): locale.setlocale(locale.LC_ALL, '') except: locale.setlocale(locale.LC_ALL, 'en_US.utf8') - """try: - loc = locale.getlocale() - filename = "res/messages_%s.mo" % locale.getlocale()[0][0:2] - print "Opening message file %s for locale %s." % (filename, loc[0]) - trans = gettext.GNUTranslations(open(filename, "rb")) - except (IOError, TypeError, IndexError): - print "Locale not found. Using default messages." - trans = gettext.NullTranslations() - trans.install()""" + #try: + # loc = locale.getlocale() + # filename = "res/messages_%s.mo" % locale.getlocale()[0][0:2] + # print "Opening message file %s for locale %s." % (filename, loc[0]) + # trans = gettext.GNUTranslations(open(filename, "rb")) + #except (IOError, TypeError, IndexError): + # print "Locale not found. Using default messages." + # trans = gettext.NullTranslations() + #trans.install() if __name__ == '__main__': init_localization() + + print('Attempting initialization of configuration manager singleton.') + config = ConfigurationManager() + logger = logging.getLogger('starrypy') logger.setLevel(9) - if TRACE: - trace_logger = logging.FileHandler("trace.log") - trace_logger.setLevel("TRACE") - trace_logger.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")) - logger.addHandler(trace_logger) - logger.trace("Initialized trace logger.") - - fh_d = logging.FileHandler("debug.log") - fh_d.setLevel(logging.DEBUG) - fh_w = logging.FileHandler("server.log") - fh_w.setLevel(logging.INFO) - sh = logging.StreamHandler(sys.stdout) - sh.setLevel(logging.INFO) - logger.addHandler(sh) - logger.addHandler(fh_d) - logger.addHandler(fh_w) - logger.trace("Attempting initialization of configuration manager singleton.") - config = ConfigurationManager() - logger.trace("Attemping to set logging formatters from configuration.") - console_formatter = logging.Formatter(config.logging_format_console) - logfile_formatter = logging.Formatter(config.logging_format_logfile) - debugfile_formatter = logging.Formatter(config.logging_format_debugfile) - fh_d.setFormatter(debugfile_formatter) - fh_w.setFormatter(logfile_formatter) - sh.setFormatter(console_formatter) + log_format = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s # %(message)s') + if config.log_level == 'DEBUG': + log_level = logging.DEBUG + else: + log_level = logging.INFO + + print('Setup console logging...') + console_handle = logging.StreamHandler(sys.stdout) + console_handle.setLevel(log_level) + logger.addHandler(console_handle) + console_handle.setFormatter(log_format) + + print('Setup file-based logging...') + logfile_handle = logging.FileHandler("server.log") + logfile_handle.setLevel(log_level) + logger.addHandler(logfile_handle) + logfile_handle.setFormatter(log_format) if config.port_check: logger.debug("Port check enabled. Performing port check to %s:%d", config.upstream_hostname, From f882609f4c2179334b28d0e43772f50a4b690911 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Mon, 2 Feb 2015 21:57:46 -0500 Subject: [PATCH 64/95] Fixed ship-based warping for bookmarks and PoI. Remade /spawn as a convenince command based on the PoI system. Ship-to-ship warping does not work currently. My guess is that, reading celestial coordinates from a player's protocol is currently not working as expected. This is less imporant for production, so I'll fix it whenever I get to it. --- config/pois.json | 2 +- packets/packet_types.py | 9 ++++ plugins/bookmarks_plugin/bookmarks_plugin.py | 54 +++++++++----------- plugins/poi_plugin/poi_plugin.py | 45 +++++++++------- plugins/warpy_plugin/warpy_plugin.py | 16 +----- utility_functions.py | 7 ++- 6 files changed, 66 insertions(+), 67 deletions(-) diff --git a/config/pois.json b/config/pois.json index 39d1633..afec3fd 100644 --- a/config/pois.json +++ b/config/pois.json @@ -1 +1 @@ -[["-30562840:658406569:-263745435:3:6", "spawn"], ["-30562840:658406569:-263745435:4:0", "forest"]] \ No newline at end of file +[["-30562840:658406569:-263745435:4:0", "forest"], ["-30562840:658406569:-263745435:3:6", "spawn"]] \ No newline at end of file diff --git a/packets/packet_types.py b/packets/packet_types.py index 0ea1ed6..377e790 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -205,6 +205,15 @@ def _decode(self, obj, context): fly_ship = lambda name="fly_ship": Struct(name, celestial_coordinate()) +fly_ship_write = lambda x=0, y=0, z=0, planet=0, satellite=0: fly_ship().build( + Container( + celestial_coordinate=Container( + x=x, + y=y, + z=z, + planet=planet, + satellite=satellite))) + # partially correct. Needs work on dungeon ID value world_start = lambda name="world_start": Struct(name, Variant("planet"), # rename to templateData? diff --git a/plugins/bookmarks_plugin/bookmarks_plugin.py b/plugins/bookmarks_plugin/bookmarks_plugin.py index 83ad309..c2a7989 100644 --- a/plugins/bookmarks_plugin/bookmarks_plugin.py +++ b/plugins/bookmarks_plugin/bookmarks_plugin.py @@ -3,7 +3,7 @@ import json from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels -from packets import player_warp_write, Packets +from packets import Packets, fly_ship, fly_ship_write from utility_functions import build_packet @@ -13,7 +13,7 @@ class Bookmarks(SimpleCommandPlugin): """ name = "bookmarks_plugin" depends = ['command_dispatcher', 'player_manager'] - commands = ["bookmark", "remove", "goto"] + commands = ["bookmark_add", "bookmark_del", "goto"] auto_activate = True def activate(self): @@ -22,8 +22,8 @@ def activate(self): self.verify_path("./config/bookmarks") @permissions(UserLevels.GUEST) - def bookmark(self, name): - """Bookmarks a planet for fast warp routes.\nSyntax: /bookmark (name)""" + def bookmark_add(self, name): + """Bookmarks a planet for fast warp routes.\nSyntax: /bookmark_add (name)""" filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" try: with open(filename) as f: @@ -45,7 +45,7 @@ def bookmark(self, name): warps.append(warp[1]) warpnames = "^green;,^yellow; ".join(warps) if warpnames == "": warpnames = "^gray;(none)^green;" - self.protocol.send_chat_message(self.bookmark.__doc__) + self.protocol.send_chat_message(self.bookmark_add.__doc__) self.protocol.send_chat_message("Please, provide a valid bookmark name!\nBookmarks: ^yellow;" + warpnames) return @@ -61,8 +61,8 @@ def bookmark(self, name): self.savebms() @permissions(UserLevels.GUEST) - def remove(self, name): - """Removes current planet from bookmarks.\nSyntax: /remove (name)""" + def bookmark_del(self, name): + """Removes current planet from bookmarks.\nSyntax: /bookmark_del (name)""" filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" try: with open(filename) as f: @@ -77,7 +77,7 @@ def remove(self, name): warps.append(warp[1]) warpnames = "^green;,^yellow; ".join(warps) if warpnames == "": warpnames = "^gray;(none)^green;" - self.protocol.send_chat_message(self.remove.__doc__) + self.protocol.send_chat_message(self.bookmark_del.__doc__) self.protocol.send_chat_message("Please, provide a valid bookmark name!\nBookmarks: ^yellow;" + warpnames) return @@ -118,26 +118,18 @@ def goto(self, name): for warp in self.bookmarks: if warp[1] == name: x, y, z, planet, satellite = warp[0].split(":") - x, y, z, planet, satellite = map((x, y, z, planet, satellite)) - warp_packet = build_packet(Packets.PLAYER_WARP, - player_warp_write(t="WARP_TO", - x=x, - y=y, - z=z, - planet=planet, - satellite=satellite)) + x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) + warp_packet = build_packet(Packets.FLY_SHIP, + fly_ship_write(x=x, + y=y, + z=z, + planet=planet, + satellite=satellite)) self.protocol.client_protocol.transport.write(warp_packet) self.protocol.send_chat_message("Warp drive engaged! Warping to ^yellow;%s^green;." % name) return self.protocol.send_chat_message("There is no bookmark named: ^yellow;%s" % name) - def verify_path(self, path): - try: - os.makedirs(path) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - def savebms(self): filename = "./config/bookmarks/" + self.protocol.player.uuid + ".json" try: @@ -147,10 +139,12 @@ def savebms(self): self.logger.exception("Couldn't save bookmarks.") raise - def beam_to_planet(self, where): - warp_packet = build_packet(Packets.PLAYER_WARP, player_warp_write(t="WARP_DOWN")) - self.protocol.client_protocol.transport.write(warp_packet) - self.protocol.send_chat_message("Beamed down to ^yellow;%s^green; and your ship will arrive soon." % where) - self.factory.broadcast_planet( - "%s^green; beamed down to the planet" % self.protocol.player.colored_name(self.config.colors), - planet=self.protocol.player.planet) + def verify_path(self, path): + """ + Helper function to make sure path exists, and create if it doesn't. + """ + try: + os.makedirs(path) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise diff --git a/plugins/poi_plugin/poi_plugin.py b/plugins/poi_plugin/poi_plugin.py index 7ed195f..24d0322 100644 --- a/plugins/poi_plugin/poi_plugin.py +++ b/plugins/poi_plugin/poi_plugin.py @@ -2,7 +2,7 @@ #from twisted.internet import reactor from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels -from packets import player_warp_write, Packets, fly_ship +from packets import Packets, fly_ship, fly_ship_write from utility_functions import build_packet @@ -12,7 +12,7 @@ class PointsofInterest(SimpleCommandPlugin): """ name = "poi_plugin" depends = ['command_dispatcher', 'player_manager'] - commands = ["poi_set", "poi_del", "poi"] + commands = ["poi_set", "poi_del", "poi", "spawn"] auto_activate = True def after_fly_ship(self, data): @@ -90,19 +90,36 @@ def poi(self, name): if warp[1] == name: x, y, z, planet, satellite = warp[0].split(":") x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) - warp_packet = build_packet(Packets.PLAYER_WARP, - player_warp_write(t="WARP_TO", - x=x, - y=y, - z=z, - planet=planet, - satellite=satellite)) + warp_packet = build_packet(Packets.FLY_SHIP, + fly_ship_write(x=x, + y=y, + z=z, + planet=planet, + satellite=satellite)) self.protocol.client_protocol.transport.write(warp_packet) self.protocol.send_chat_message("Warp drive engaged! Warping to ^yellow;%s^green;." % name) - #reactor.callLater(1, self.beam_to_planet, name) # enable this for 1s delayed warping of a player return self.protocol.send_chat_message("There is no PoI named ^yellow;%s^green;." % name) + @permissions(UserLevels.GUEST) + def spawn(self, data): + """Warps your ship to spawn.\nSyntax: /spawn""" + for warp in self.pois: + if warp[1] == 'spawn': + x, y, z, planet, satellite = warp[0].split(":") + x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) + warp_packet = build_packet(Packets.FLY_SHIP, + fly_ship_write(x=x, + y=y, + z=z, + planet=planet, + satellite=satellite)) + self.protocol.client_protocol.transport.write(warp_packet) + self.protocol.send_chat_message("Warp drive engaged! Warping to ^yellow;%s^green;." % 'Spawn') + return + else: + self.protocol.send_chat_message("The spawn planet must be set first!") + def savepois(self): try: with open("./config/pois.json", "w") as f: @@ -110,11 +127,3 @@ def savepois(self): except: self.logger.exception("Couldn't save PoI's.") raise - - def beam_to_planet(self, where): - warp_packet = build_packet(Packets.PLAYER_WARP, player_warp_write(t="WARP_DOWN")) - self.protocol.client_protocol.transport.write(warp_packet) - self.protocol.send_chat_message("Beamed down to ^yellow;%s^green; and your ship will arrive soon." % where) - self.factory.broadcast_planet( - "%s^green; beamed down to the planet" % self.protocol.player.colored_name(self.config.colors), - planet=self.protocol.player.planet) diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 1b18a15..8268638 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -1,7 +1,7 @@ # -*- coding: UTF-8 -*- from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels -from packets import player_warp_write, Packets, player_warp +from packets import Packets, player_warp, player_warp_write, fly_ship, fly_ship_write from utility_functions import build_packet, move_ship_to_coords, extract_name @@ -11,7 +11,7 @@ class Warpy(SimpleCommandPlugin): """ name = "warpy_plugin" depends = ['command_dispatcher', 'player_manager'] - commands = ["warp", "warp_ship", "outpost", "spawn"] + commands = ["warp", "warp_ship", "outpost"] auto_activate = True def activate(self): @@ -45,7 +45,6 @@ def warp(self, name): return self.warp_player_to_player(first_name, second_name) -# THIS IS CURRENTLY BROKEN! @permissions(UserLevels.ADMIN) def warp_ship(self, location): """Warps a player ship to another players ship.\nSyntax: /warp_ship [player] (to player)""" @@ -66,7 +65,6 @@ def warp_ship(self, location): self.protocol.send_chat_message(str(e)) return self.move_player_ship_to_other(first_name, second_name) -#!!!!!!!!!!!!!!!!!!!!!!! @permissions(UserLevels.MODERATOR) def outpost(self, name): @@ -177,13 +175,3 @@ def warp_player_to_outpost(self, player_string): else: self.protocol.send_chat_message("No player by the name ^yellow;%s^green; found." % player_string) self.protocol.send_chat_message(self.warp.__doc__) - - @permissions(UserLevels.GUEST) - def spawn(self, data): - """Warps your ship to spawn.\nSyntax: /spawn""" - on_ship = self.protocol.player.on_ship - if not on_ship: - self.protocol.send_chat_message("You need to be on a ship!") - return - self.plugins['warpy_plugin'].move_player_ship(self.protocol, [x for x in self._spawn]) - self.protocol.send_chat_message("Moving your ship to spawn.") diff --git a/utility_functions.py b/utility_functions.py index c57a524..ed846a7 100644 --- a/utility_functions.py +++ b/utility_functions.py @@ -64,10 +64,9 @@ def move_ship_to_coords(protocol, x, y, z, planet, satellite): logger.info("Moving %s's ship to coordinates: %s", protocol.player.name, ":".join((str(x), str(y), str(z), str(planet), str(satellite)))) x, y, z, planet, satellite = map(int, (x, y, z, planet, satellite)) - warp_packet = build_packet(packets.Packets.PLAYER_WARP, - packets.player_warp_write(t="WARP_TO", x=x, y=y, z=z, - planet=planet, - satellite=satellite, player="".encode('utf-8'))) + warp_packet = build_packet(packets.Packets.FLY_SHIP, + packets.fly_ship_write(x=x, y=y, z=z, planet=planet, + satellite=satellite)) protocol.client_protocol.transport.write(warp_packet) From 7537ef1a545786f003c8e7234eed2147f9017d73 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 00:29:47 -0500 Subject: [PATCH 65/95] Remove visibility of other .json files from git commits. No one needs to see my test PoI's and bookmarks --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 37d2614..8697f98 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ nosetests.xml .pydevproject # Project specific -*config.json +*.json *.db *.db-journal *.log From c35caecb9f137c473dc03d15233f70a8ff7183eb Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 00:49:06 -0500 Subject: [PATCH 66/95] Re-added modchatter plugin, and tested to be sure it worked --- config/config.json.default | 3 ++ plugins/mod_chatter/__init__.py | 1 + plugins/mod_chatter/mod_chatter.py | 47 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 plugins/mod_chatter/__init__.py create mode 100644 plugins/mod_chatter/mod_chatter.py diff --git a/config/config.json.default b/config/config.json.default index 934e18b..e77e7e8 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -47,6 +47,9 @@ "port": 6667, "server": "irc.freenode.net" }, + "mod_chatter": { + "auto_activate": true + }, "motd_plugin": { "auto_activate": true, "motd": "Welcome to the server! Play nice." diff --git a/plugins/mod_chatter/__init__.py b/plugins/mod_chatter/__init__.py new file mode 100644 index 0000000..4719056 --- /dev/null +++ b/plugins/mod_chatter/__init__.py @@ -0,0 +1 @@ +from mod_chatter import ModChatter diff --git a/plugins/mod_chatter/mod_chatter.py b/plugins/mod_chatter/mod_chatter.py new file mode 100644 index 0000000..62f2111 --- /dev/null +++ b/plugins/mod_chatter/mod_chatter.py @@ -0,0 +1,47 @@ +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +import packets +from datetime import datetime + + +class ModChatter(SimpleCommandPlugin): + """Adds support for moderators/admins/owner group chatter.""" + name = "mod_chatter" + depends = ['command_dispatcher', 'player_manager'] + commands = ["modchat", "mc"] + auto_activate = True + + def activate(self): + super(ModChatter, self).activate() + self.prefix = self.config.chat_prefix + self.player_manager = self.plugins['player_manager'].player_manager + + @permissions(UserLevels.MODERATOR) + def modchat(self, data): + """Allows mod-only chatting.\nSyntax: /modchat (msg)""" + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^red;<" + now.strftime("%H:%M") + "> ^yellow;" + else: + timestamp = "" + if len(data) == 0: + self.protocol.send_chat_message(self.modchat.__doc__) + return + try: + message = " ".join(data) + for protocol in self.factory.protocols.itervalues(): + if protocol.player.access_level >= UserLevels.MODERATOR: + protocol.send_chat_message(timestamp + + "%sModChat: ^yellow;<%s^yellow;> %s%s" % (self.config.colors["admin"], self.protocol.player.colored_name(self.config.colors), + self.config.colors["admin"],message.decode("utf-8"))) + self.logger.info("Received an admin message from %s. Message: %s", self.protocol.player.name, + message.decode("utf-8")) + except ValueError as e: + self.protocol.send_chat_message(self.modchat.__doc__) + except TypeError as e: + self.protocol.send_chat_message(self.modchat.__doc__) + + @permissions(UserLevels.MODERATOR) + def mc(self, data): + """Allows mod-only chatting.\nSyntax: /modchat (msg)""" + self.modchat(data) From 834db725aba832057c7e75acbe7b2d9fe235c167 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 04:51:33 -0500 Subject: [PATCH 67/95] Worked on chat system. Fixed packet structure, resolved issue #34 regarding 'local' chat skipping IRC. Added uptime plugin --- packets/packet_types.py | 30 ++++++++++++++++------------- plugins/chat_logger/chat_logger.py | 5 ++++- plugins/irc_plugin/irc_plugin.py | 4 ++-- plugins/mod_chatter/mod_chatter.py | 1 - plugins/uptime/__init__.py | 1 + plugins/uptime/uptime.py | 31 ++++++++++++++++++++++++++++++ server.py | 4 ++-- 7 files changed, 57 insertions(+), 19 deletions(-) create mode 100644 plugins/uptime/__init__.py create mode 100644 plugins/uptime/uptime.py diff --git a/packets/packet_types.py b/packets/packet_types.py index 377e790..b72a291 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -79,13 +79,6 @@ class EntityType(IntEnum): NPC = 8 -class MessageContextMode(IntEnum): - CHANNEL = 0 - BROADCAST = 1 - WHISPER = 2 - COMMAND_RESULT = 3 - - class PacketOutOfOrder(Exception): pass @@ -140,8 +133,12 @@ def _decode(self, obj, context): # corrected. needs testing chat_received = lambda name="chat_received": Struct(name, - Byte("mode"), - star_string("chat_channel"), + Enum(Byte("mode"), + CHANNEL=0, + BROADCAST=1, + WHISPER=2, + COMMAND_RESULT=3), + star_string("channel"), UBInt32("client_id"), star_string("name"), star_string("message")) @@ -155,6 +152,11 @@ def _decode(self, obj, context): PARTY=2) ) +chat_sent_write = lambda message, send_mode: chat_sent().build( + Container( + message=message, + send_mode=send_mode)) + # quite a bit of guesswork and hackery here with the ship_upgrades. client_connect = lambda name="client_connect": Struct(name, VLQ("asset_digest_length"), @@ -236,10 +238,12 @@ def _decode(self, obj, context): Byte("variant_type"), star_string("description")) -give_item_write = lambda name, count: give_item().build(Container(name=name, - count=count, - variant_type=7, - description='')) +give_item_write = lambda name, count: give_item().build( + Container( + name=name, + count=count, + variant_type=7, + description='')) update_world_properties = lambda name="world_properties": Struct(name, UBInt8("count"), diff --git a/plugins/chat_logger/chat_logger.py b/plugins/chat_logger/chat_logger.py index 756abcb..d46f57a 100644 --- a/plugins/chat_logger/chat_logger.py +++ b/plugins/chat_logger/chat_logger.py @@ -3,9 +3,12 @@ class ChatLogger(BasePlugin): + """ + Plugin which parses player chatter into the log file. + """ name = "chat_logger" def on_chat_sent(self, data): parsed = chat_sent().parse(data.data) parsed.message = parsed.message.decode("utf-8") - self.logger.info("Chat message sent: <%s> %s", self.protocol.player.name, parsed.message) \ No newline at end of file + self.logger.info("Chat message sent: <%s> %s", self.protocol.player.name, parsed.message) diff --git a/plugins/irc_plugin/irc_plugin.py b/plugins/irc_plugin/irc_plugin.py index 2ee2655..99cf1e2 100644 --- a/plugins/irc_plugin/irc_plugin.py +++ b/plugins/irc_plugin/irc_plugin.py @@ -47,6 +47,8 @@ def deactivate(self): def on_chat_sent(self, data): parsed = chat_sent().parse(data.data) + if parsed.send_mode == 'LOCAL': + return True if not parsed.message.startswith('/'): for p in self.irc_factory.irc_clients.itervalues(): p.msg(self.channel, "<%s> %s" % (self.protocol.player.name.encode("utf-8"), parsed.message.encode("utf-8"))) @@ -55,10 +57,8 @@ def on_chat_sent(self, data): def on_client_connect(self, data): parsed = client_connect().parse(data.data) self.logger.info(parsed.name) - for p in self.irc_factory.irc_clients.itervalues(): p.msg(self.channel, "%s connected" % parsed.name.encode("utf-8")) - return True def on_client_disconnect_request(self, data): diff --git a/plugins/mod_chatter/mod_chatter.py b/plugins/mod_chatter/mod_chatter.py index 62f2111..1240534 100644 --- a/plugins/mod_chatter/mod_chatter.py +++ b/plugins/mod_chatter/mod_chatter.py @@ -13,7 +13,6 @@ class ModChatter(SimpleCommandPlugin): def activate(self): super(ModChatter, self).activate() - self.prefix = self.config.chat_prefix self.player_manager = self.plugins['player_manager'].player_manager @permissions(UserLevels.MODERATOR) diff --git a/plugins/uptime/__init__.py b/plugins/uptime/__init__.py new file mode 100644 index 0000000..cae4653 --- /dev/null +++ b/plugins/uptime/__init__.py @@ -0,0 +1 @@ +from uptime import UptimePlugin \ No newline at end of file diff --git a/plugins/uptime/uptime.py b/plugins/uptime/uptime.py new file mode 100644 index 0000000..151c8f7 --- /dev/null +++ b/plugins/uptime/uptime.py @@ -0,0 +1,31 @@ +# -*- coding: UTF-8 -*- +from datetime import datetime + +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +from server import VERSION + + +class UptimePlugin(SimpleCommandPlugin): + """ + Very simple plugin that responds to /uptime with the time StarryPy is running. + """ + name = "uptime_plugin" + depends = ["command_dispatcher", "player_manager"] + commands = ["uptime"] + auto_activate = True + + def activate(self): + super(UptimePlugin, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + self.started_at = datetime.now() + + @permissions(UserLevels.GUEST) + def uptime(self, data_): + """Displays server uptime and version.\nSyntax: /uptime""" + now = datetime.now() + delta = now - self.started_at + self.protocol.send_chat_message("<" + now.strftime("%H:%M") + "> Uptime: ^cyan;%d^green; day(s), ^cyan;%d^green; hour(s), ^cyan;%d^green; min(s), ^cyan;%d^green; user(s)\nRunning Starbound server wrapper ^magenta;StarryPy ^cyan;v%s" % ( + delta.days, (delta.seconds / 3600) % 3600, (delta.seconds / 60) % 60, + len(self.player_manager.who()), VERSION) + ) diff --git a/server.py b/server.py index 0cd0f46..8b6c132 100644 --- a/server.py +++ b/server.py @@ -428,7 +428,7 @@ def handle_starbound_packets(self, p): """ return self.call_mapping[p.id](p) - def send_chat_message(self, text, mode=0, channel='', name=''): + def send_chat_message(self, text, mode='BROADCAST', channel='', name=''): """ Convenience function to send chat messages to the client. Note that this does *not* send messages to the server at large; broadcast should be @@ -451,7 +451,7 @@ def send_chat_message(self, text, mode=0, channel='', name=''): ' %s with mode %s with reported username of %s with' ' message: %s'), self.player.name, channel, mode, name, text) chat_data = packets.chat_received().build(Container(mode=mode, - chat_channel=channel, + channel=channel, client_id=0, name=name, message=text.encode("utf-8"))) From a2929275a3f4f8681b0e53c4a0a24be4613a5eb6 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 04:59:04 -0500 Subject: [PATCH 68/95] Fixed issue #22 regarding weird spacing. --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 12174f1..6de1364 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -172,17 +172,15 @@ def kick(self, data): self.factory.broadcast("%s^green; kicked %s ^green;(reason: ^yellow;%s^green;)" % (self.protocol.player.colored_name(self.config.colors), info.colored_name(self.config.colors), - " ".join(reason))) + "".join(reason))) self.logger.info("%s kicked %s (reason: %s)", self.protocol.player.name, info.name, - " ".join(reason)) + "".join(reason)) tp = self.factory.protocols[info.protocol] tp.die() else: self.protocol.send_chat_message("Couldn't find a user by the name ^yellow;%s^green;." % name) return False - - @permissions(UserLevels.ADMIN) def ban(self, data): """Bans an IP or a Player (by name).\nSyntax: /ban (IP | player)\nTip: Use /whois (player) to get IP""" From dee6f71a7c68eb81faacd7cdf8bd70d01e8693bb Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 11:50:05 -0500 Subject: [PATCH 69/95] Re-built a custom logging level (VDEBUG) for the more verbose messages. --- __init__.py | 7 +++++++ plugins/poi_plugin/poi_plugin.py | 5 ----- server.py | 29 +++++++++++++++++++---------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/__init__.py b/__init__.py index ade1461..34a33c5 100644 --- a/__init__.py +++ b/__init__.py @@ -1 +1,8 @@ import logging + +VDEBUG_LVL = 9 +logging.addLevelName(VDEBUG_LVL, "VDEBUG") +def vdebug(self, message, *args, **kws): + if self.isEnabledFor(VDEBUG_LVL): + self._log(VDEBUG_LVL, message, args, **kws) +logging.Logger.vdebug = vdebug diff --git a/plugins/poi_plugin/poi_plugin.py b/plugins/poi_plugin/poi_plugin.py index 24d0322..37b81a2 100644 --- a/plugins/poi_plugin/poi_plugin.py +++ b/plugins/poi_plugin/poi_plugin.py @@ -1,5 +1,4 @@ import json -#from twisted.internet import reactor from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import permissions, UserLevels from packets import Packets, fly_ship, fly_ship_write @@ -15,9 +14,6 @@ class PointsofInterest(SimpleCommandPlugin): commands = ["poi_set", "poi_del", "poi", "spawn"] auto_activate = True - def after_fly_ship(self, data): - self.logger.debug("Coords: %s", fly_ship().parse(data.data)) - def activate(self): super(PointsofInterest, self).activate() self.player_manager = self.plugins['player_manager'].player_manager @@ -27,7 +23,6 @@ def activate(self): except: self.pois = [] - # Commands that allows admins to define Planets of Interest (PoI) any player can /poi to. @permissions(UserLevels.ADMIN) def poi_set(self, name): """Sets current planet as Planet of Interest (PoI).\nSyntax: /poi_set (name)""" diff --git a/server.py b/server.py index 8b6c132..146a12c 100644 --- a/server.py +++ b/server.py @@ -24,6 +24,13 @@ VERSION = "1.4.4" +VDEBUG_LVL = 9 +logging.addLevelName(VDEBUG_LVL, "VDEBUG") +def vdebug(self, message, *args, **kws): + if self.isEnabledFor(VDEBUG_LVL): + self._log(VDEBUG_LVL, message, args, **kws) +logging.Logger.vdebug = vdebug + def port_check(upstream_hostname, upstream_port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(1) @@ -48,7 +55,7 @@ def __init__(self): """ """ self.id = str(uuid4().hex) - logger.debug("Creating protocol with ID %s.", self.id) + logger.vdebug("Creating protocol with ID %s.", self.id) self.factory.protocols[self.id] = self self.player = None self.state = None @@ -447,7 +454,7 @@ def send_chat_message(self, text, mode='BROADCAST', channel='', name=''): self.send_chat_message(line) return if self.player is not None: - logger.debug(('Calling send_chat_message from player %s on channel' + logger.vdebug(('Calling send_chat_message from player %s on channel' ' %s with mode %s with reported username of %s with' ' message: %s'), self.player.name, channel, mode, name, text) chat_data = packets.chat_received().build(Container(mode=mode, @@ -455,12 +462,12 @@ def send_chat_message(self, text, mode='BROADCAST', channel='', name=''): client_id=0, name=name, message=text.encode("utf-8"))) - logger.debug("Built chat payload. Data: %s", chat_data.encode("hex")) + logger.vdebug("Built chat payload. Data: %s", chat_data.encode("hex")) chat_packet = build_packet(packets.Packets.CHAT_RECEIVED, chat_data) - logger.debug("Built chat packet. Data: %s", chat_packet.encode("hex")) + logger.vdebug("Built chat packet. Data: %s", chat_packet.encode("hex")) self.transport.write(chat_packet) - logger.debug("Sent chat message with text: %s", text) + logger.vdebug("Sent chat message with text: %s", text) def write(self, data): """ @@ -635,12 +642,12 @@ def buildProtocol(self, address): :rtype : Protocol """ - logger.debug("Building protocol to address %s", address) + logger.vdebug("Building protocol to address %s", address) p = ServerFactory.buildProtocol(self, address) return p def reap_dead_protocols(self): - logger.debug("Reaping dead connections.") + logger.vdebug("Reaping dead connections.") count = 0 start_time = datetime.datetime.now() for protocol in self.protocols.itervalues(): @@ -658,7 +665,7 @@ def reap_dead_protocols(self): elif count > 1: logger.info("%d connections reaped.") else: - logger.debug("No connections reaped.") + logger.vdebug("No connections reaped.") class StarboundClientFactory(ClientFactory): @@ -668,11 +675,11 @@ class StarboundClientFactory(ClientFactory): protocol = ClientProtocol def __init__(self, server_protocol): - logger.debug("Client protocol instantiated.") + logger.vdebug("Client protocol instantiated.") self.server_protocol = server_protocol def buildProtocol(self, address): - logger.debug("Building protocol in StarboundClientFactory to address %s", address) + logger.vdebug("Building protocol in StarboundClientFactory to address %s", address) protocol = ClientFactory.buildProtocol(self, address) protocol.server_protocol = self.server_protocol return protocol @@ -703,6 +710,8 @@ def init_localization(): log_format = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s # %(message)s') if config.log_level == 'DEBUG': log_level = logging.DEBUG + elif config.log_level == 'VDEBUG': + log_level = "VDEBUG" else: log_level = logging.INFO From 517675cb1d887e992a30723d5df76c32286b386e Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 18:54:17 -0500 Subject: [PATCH 70/95] added auto-reconnecting functionality to the IRC Bot, in case of connection loss --- plugins/irc_plugin/irc_manager.py | 46 +++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/plugins/irc_plugin/irc_manager.py b/plugins/irc_plugin/irc_manager.py index 1f1b024..4128434 100644 --- a/plugins/irc_plugin/irc_manager.py +++ b/plugins/irc_plugin/irc_manager.py @@ -1,11 +1,9 @@ -# twisted imports from twisted.words.protocols import irc from twisted.internet import reactor, protocol from uuid import uuid4 class StarryPyIrcBot(irc.IRCClient): - def __init__(self, logger, nickname, nickserv_password, factory, broadcast_target, colors, echo_from_channel): self.logger = logger self.nickname = nickname @@ -16,23 +14,35 @@ def __init__(self, logger, nickname, nickserv_password, factory, broadcast_targe self.colors = colors self.echo_from_channel = echo_from_channel + def connectionMade(self): + irc.IRCClient.connectionMade(self) + self.logger.info("IRC connection made") + + def connectionLost(self, reason): + irc.IRCClient.connectionLost(self, reason) + self.logger.info("IRC connection lost: %s", format(reason)) + def signedOn(self): + """Called when bot has successfully signed on to server.""" if self.nickserv_password: self.msg("NickServ", "identify %s" % self.nickserv_password) if self.factory.target.startswith("#"): self.join(self.factory.target) else: self.send_greeting(self.factory.target) - - self.logger.info("Connected to IRC") + self.logger.info("Signed into IRC") def joined(self, target): + """This will get called when the bot joins the channel.""" + self.logger.debug("Sucesssfully joined the IRC channel %s.", self.factory.target) self.send_greeting(target) def send_greeting(self, target): + """IRC channel greeting function""" self.msg(target, "%s is live!" % self.nickname) def privmsg(self, user, target, msg): + """This will get called when the bot receives a message.""" user = user.split('!', 1)[0] self.logger.info("IRC Message <%s>: %s" % (user, msg)) if self.echo_from_channel: @@ -45,18 +55,31 @@ def privmsg(self, user, target, msg): )) def action(self, user, target, msg): + """This will get called when a user performs an action in the channel""" user = user.split('!', 1)[0] self.logger.info("IRC Action: %s %s" % (user, msg)) + def irc_NICK(self, prefix, params): + """Called when an IRC user changes their nickname.""" + old_nick = prefix.split('!')[0] + new_nick = params[0] + self.logger.info("%s is now known as %s" % (old_nick, new_nick)) + + +class StarryPyIrcBotFactory(protocol.ReconnectingClientFactory): + """Factory for IRC bot.""" + + # Parameters used in the auto-reconnect system. Currently hard-coded. Will + # eventually move them to the config file. + maxRetries = 100 + initalDelay = 1.0 -class StarryPyIrcBotFactory(protocol.ClientFactory): def __init__(self, target, logger, nickname, nickserv_password, broadcast_target, colors, echo_from_channel): self.nickname = nickname try: self.nickserv_password = nickserv_password except AttributeError: self.nickserv_password = None - self.target = target self.broadcast_target = broadcast_target self.colors = colors @@ -64,13 +87,20 @@ def __init__(self, target, logger, nickname, nickserv_password, broadcast_target self.irc_clients = {} self.echo_from_channel = echo_from_channel + def startedConnecting(self, connector): + self.logger.debug("Factory attempting to connect...") + def buildProtocol(self, addr): irc_client = StarryPyIrcBot(self.logger, self.nickname, self.nickserv_password, self, self.broadcast_target, self.colors, self.echo_from_channel) + irc_client.factory = self self.irc_clients[irc_client.id] = irc_client + self.resetDelay() return irc_client def clientConnectionLost(self, connector, reason): - connector.connect() + self.logger.error("IRC connection lost, reconnecting") + protocol.ReconnectingClientFactory.clientConnectionLost(self, connector, reason) def clientConnectionFailed(self, connector, reason): - self.logger.error("connection failed: %s" % reason) + self.logger.error("IRC connection failed: %s" % format(reason)) + protocol.ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) From 782447c13860d53da3d8d1674f8f1eeb4b5e2e52 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 3 Feb 2015 19:41:23 -0500 Subject: [PATCH 71/95] Fixed some over-verbosity issues (I forgot to turn off). --- plugins/core/player_manager/manager.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index a510ec1..d51d7e2 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -18,14 +18,11 @@ @contextmanager def _autoclosing_session(sm): session = sm() - try: yield session - except: session.rollback() raise - finally: session.close() @@ -162,12 +159,12 @@ class Player(Base): ips = relationship("IPAddress", order_by="IPAddress.id", backref="players") def colored_name(self, colors): - logger.debug("Building colored name.") + logger.vdebug("Building colored name.") color = colors[UserLevels(self.access_level).lower()] - logger.debug("Color is %s", color) + logger.vdebug("Color is %s", color) name = self.name - logger.debug("Name is %s", name) - logger.debug("Returning the following data for colored name. %s:%s:%s", + logger.vdebug("Name is %s", name) + logger.vdebug("Returning the following data for colored name. %s:%s:%s", color, name, colors['default']) return color + name + colors["default"] From 907062af075dd341790705896b57bd88c2d16ded Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 00:12:05 -0500 Subject: [PATCH 72/95] Added brutus_whisper plugin (works out of the box, not modification needed). Updated config.json.defaults. --- config/config.json.default | 11 +- plugins/brutus_whisper/__init__.py | 1 + plugins/brutus_whisper/brutus_whisper.py | 123 +++++++++++++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 plugins/brutus_whisper/__init__.py create mode 100644 plugins/brutus_whisper/brutus_whisper.py diff --git a/config/config.json.default b/config/config.json.default index e77e7e8..fa86e62 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -28,6 +28,9 @@ "bookmarks_plugin": { "auto_activate": true }, + "brutus_whisper": { + "auto_activate": true + }, "chat_logger": { "auto_activate": true }, @@ -165,7 +168,10 @@ "spinningrocket", "stationaryrocket" ], - "protected_planets": [] + "player_planets": { + }, + "protected_planets": [ + ] }, "player_manager": { "auto_activate": true, @@ -186,6 +192,9 @@ "starbound_config_manager": { "auto_activate": true }, + "uptime_plugin": { + "auto_activate": true + }, "user_management_commands": { "auto_activate": true }, diff --git a/plugins/brutus_whisper/__init__.py b/plugins/brutus_whisper/__init__.py new file mode 100644 index 0000000..c03c152 --- /dev/null +++ b/plugins/brutus_whisper/__init__.py @@ -0,0 +1 @@ +from brutus_whisper import BRWhisperPlugin \ No newline at end of file diff --git a/plugins/brutus_whisper/brutus_whisper.py b/plugins/brutus_whisper/brutus_whisper.py new file mode 100644 index 0000000..70a597e --- /dev/null +++ b/plugins/brutus_whisper/brutus_whisper.py @@ -0,0 +1,123 @@ +#=========================================================== +# BRWhisperPlugin +# Author: FZFalzar/Duck of Brutus.SG Starbound (http://steamcommunity.com/groups/BrutusSG) +# Version: v0.1 +# Description: A better whisper plugin with reply and SocialSpy +#=========================================================== + +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +from utility_functions import extract_name +from datetime import datetime + +class BRWhisperPlugin(SimpleCommandPlugin): + name = "brutus_whisper" + depends = ['command_dispatcher', 'player_manager'] + commands = ["whisper", "w", "r", "ss"] + auto_activate = True + + def activate(self): + super(BRWhisperPlugin, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + self.reply_history = dict() + self.sspy_enabled_dict = dict() + + @permissions(UserLevels.GUEST) + def whisper(self, data): + """Sends a message to target player.\nSyntax: /whisper (player) (msg)""" + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^orange;<" + now.strftime("%H:%M") + "> " + else: + timestamp = "" + if len(data) == 0: + self.protocol.send_chat_message(self.whisper.__doc__) + return + try: + targetName, message = extract_name(data) + if not message: + self.protocol.send_chat_message("Invalid message!") + self.protocol.send_chat_message(self.whisper.__doc__) + return + self.logger.info("Message to %s from %s: %s" % (targetName, self.protocol.player.name, " ".join(message))) + self.sendWhisper(targetName, " ".join(message)) + except ValueError as e: + self.protocol.send_chat_message(self.whisper.__doc__) + except TypeError as e: + self.protocol.send_chat_message(self.whisper.__doc__) + + def reply(self, data): + """Replies to last player who whispered you.\nSyntax: /r (msg)""" + if len(data) == 0: + self.protocol.send_chat_message(self.reply.__doc__) + return + + #retrieve your own history, using your name as key + try: + target = self.reply_history[self.protocol.player.name] + self.sendWhisper(target, " ".join(data)) + except KeyError as e: + self.protocol.send_chat_message("You have no one to reply to!") + + @permissions(UserLevels.GUEST) + def w(self, data): + """Sends a message to target player.\nSyntax: /whisper (player) (msg)""" + self.whisper(data) + + @permissions(UserLevels.GUEST) + def r(self, data): + """Replies to last player who whispered you.\nSyntax: /r (msg)""" + self.reply(data) + + def sendWhisper(self, target, message): + now = datetime.now() + if self.config.chattimestamps: + timestamp = "<" + now.strftime("%H:%M") + "> " + else: + timestamp = "" + targetPlayer = self.player_manager.get_logged_in_by_name(target) + if targetPlayer is None: + self.protocol.send_chat_message(("Couldn't send a message to %s") % target) + return + else: + #show yourself the message + strMsgTo = "^violet;" + timestamp + "<%s^violet;> %s" % (self.protocol.player.colored_name(self.config.colors), message) + strTo = "%s" % targetPlayer.colored_name(self.config.colors) + self.protocol.send_chat_message(strMsgTo) + + #show target the message + protocol = self.factory.protocols[targetPlayer.protocol] + strMsgFrom = "^violet;" + timestamp + "<%s^violet;> %s" % (self.protocol.player.colored_name(self.config.colors), message) + strFrom = "%s" % self.protocol.player.colored_name(self.config.colors) + protocol.send_chat_message(strMsgFrom) + + #store your last sent history, so the other player can reply + #store your name using your target's name as key, so he can use his name to find you + self.reply_history[target] = self.protocol.player.name + + #send message to people with socialspy on + for key, value in self.sspy_enabled_dict.iteritems(): + sspy_player = self.player_manager.get_logged_in_by_name(key) + if sspy_player is not None: + if sspy_player.access_level >= UserLevels.OWNER and value == True: + protocol = self.factory.protocols[sspy_player.protocol] + protocol.send_chat_message("^red;" + timestamp + "%sSS: ^cyan;<%s ^green;-> %s^cyan;> ^green;%s" % (self.config.colors["admin"], strFrom, strTo, message)) + + @permissions(UserLevels.OWNER) + def ss(self, data): + """Toggles viewing of other players whispers.\nSyntax: /ss""" + try: + if not self.sspy_enabled_dict[self.protocol.player.name]: + self.sspy_enabled_dict[self.protocol.player.name] = True + self.protocol.send_chat_message("SocialSpy has been ^green;enabled^yellow;!") + else: + self.sspy_enabled_dict[self.protocol.player.name] = False + self.protocol.send_chat_message("SocialSpy has been ^red;disabled^yellow;!") + except: + if len(data) != 0 and " ".join(data).lower() in ["on", "true"]: + self.sspy_enabled_dict[self.protocol.player.name] = True + self.protocol.send_chat_message("SocialSpy has been ^green;enabled^yellow;!") + else: + self.sspy_enabled_dict[self.protocol.player.name] = False + self.protocol.send_chat_message(self.ss.__doc__) + self.protocol.send_chat_message("SocialSpy is ^red;disabled^yellow;!") From d2738bc257358eb10c24a3c1f13432bab98302b9 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 00:21:51 -0500 Subject: [PATCH 73/95] Added emotes plugin. Worked out of box, no modifcation needed. --- config/config.json.default | 3 ++ plugins/emotes/__init__.py | 1 + plugins/emotes/emotes.py | 98 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 plugins/emotes/__init__.py create mode 100644 plugins/emotes/emotes.py diff --git a/config/config.json.default b/config/config.json.default index fa86e62..ce79140 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -40,6 +40,9 @@ "command_dispatcher": { "auto_activate": true }, + "emotes_plugin": { + "auto_activate": true + }, "irc": { "auto_activate": false, "bot_nickname": "StarryPyBot", diff --git a/plugins/emotes/__init__.py b/plugins/emotes/__init__.py new file mode 100644 index 0000000..9376eec --- /dev/null +++ b/plugins/emotes/__init__.py @@ -0,0 +1 @@ +from emotes import EmotesPlugin \ No newline at end of file diff --git a/plugins/emotes/emotes.py b/plugins/emotes/emotes.py new file mode 100644 index 0000000..1088756 --- /dev/null +++ b/plugins/emotes/emotes.py @@ -0,0 +1,98 @@ +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +from datetime import datetime +from random import randrange, choice + + +class EmotesPlugin(SimpleCommandPlugin): + """ + Very simple plugin that adds /me command to StarryPy. + """ + name = "emotes_plugin" + depends = ["command_dispatcher", "player_manager"] + commands = ["me"] + auto_activate = True + + def activate(self): + super(EmotesPlugin, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + + @permissions(UserLevels.GUEST) + def me(self, data): + """Creates a player emote message.\nSyntax: /me (emote) +Predefined emotes: ^yellow;beckon^green;, ^yellow;bow^green;, ^yellow;cheer^green;, ^yellow;cower^green;, ^yellow;cry^green;, ^yellow;dance^green;, ^yellow;hug^green;, ^yellow;hugs^green;, ^yellow;kiss^green;, ^yellow;kneel^green;, ^yellow;laugh^green;, ^yellow;lol^green;, ^yellow;no^green;, ^yellow;point^green;, ^yellow;ponder^green;, ^yellow;rofl^green;, ^yellow;salute^green;, ^yellow;shrug^green;, ^yellow;sit^green;, ^yellow;sleep^green;, ^yellow;surprised^green;, ^yellow;threaten^green;, ^yellow;wave^green;, ^yellow;yes^green; +Utility emotes: ^yellow;flip^green;, ^yellow;roll^green;""" + now = datetime.now() + if len(data) == 0: + self.protocol.send_chat_message(self.me.__doc__) + return + if self.protocol.player.muted: + self.protocol.send_chat_message( + "You are currently muted and cannot emote. You are limited to commands and admin chat (prefix your lines with %s for admin chat." % (self.config.chat_prefix*2)) + return False + emote = " ".join(data) + spec_prefix = "" #we'll use this for random rolls, to prevent faking + if emote == "beckon": + emote = "beckons you to come over" + elif emote == "bow": + emote = "bows before you" + elif emote == "cheer": + emote = "cheers at you! Yay!" + elif emote == "cower": + emote = "cowers at the sight of your weapons!" + elif emote == "cry": + emote = "bursts out in tears... sob sob" + elif emote == "dance": + emote = "is busting out some moves, some sweet dance moves" + elif emote == "flip": + flipdata = ["HEADS!", "TAILS!"] + spec_prefix = "^cyan;!" #add cyan color ! infront of name or player can /me rolled ^cyan;100 + emote = "flips a coin and its... ^cyan;%s" % choice(flipdata) + elif emote == "hug": + emote = "needs a hug!" + elif emote == "hugs": + emote = "needs a hug! Many MANY hugs!" + elif emote == "kiss": + emote = "blows you a kiss <3" + elif emote == "kneel": + emote = "kneels down before you" + elif emote == "laugh": + emote = "suddenly laughs and just as suddenly stops" + elif emote == "lol": + emote = "laughs out loud -LOL-" + elif emote == "no": + emote = "disagrees" + elif emote == "point": + emote = "points somewhere in the distance" + elif emote == "ponder": + emote = "ponders if this is worth it" + elif emote == "rofl": + emote = "rolls on the floor laughing" + elif emote == "roll": + rollx=str(randrange(1,101)) + spec_prefix = "^cyan;!" #add cyan color ! infront of name or player can /me rolled ^cyan;100 + emote = "rolled ^cyan;%s" % rollx + elif emote == "salute": + emote = "salutes you" + elif emote == "shrug": + emote = "shrugs at you" + elif emote == "sit": + emote = "sits down. Oh, boy..." + elif emote == "sleep": + emote = "falls asleep. Zzz" + elif emote == "surprised": + emote = "is surprised beyond belief" + elif emote == "threaten": + emote = "is threatening you with a butter knife!" + elif emote == "wave": + emote = "waves... Helloooo there!" + elif emote == "yes": + emote = "agrees" + + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^orange;<" + now.strftime("%H:%M") + "> " + else: + timestamp = "" + self.factory.broadcast_planet(timestamp + spec_prefix + "^orange;%s %s" % (self.protocol.player.name, emote), planet=self.protocol.player.planet) + return False From 92f69dc542cefc59ce2159a940d051e978895c29 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 01:46:36 -0500 Subject: [PATCH 74/95] Added AFK plugin. Everything works. --- config/config.json.default | 3 ++ packets/packet_types.py | 7 ++- plugins/afk_plugin/__init__.py | 1 + plugins/afk_plugin/afk_plugin.py | 88 ++++++++++++++++++++++++++++++++ server.py | 3 +- 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 plugins/afk_plugin/__init__.py create mode 100644 plugins/afk_plugin/afk_plugin.py diff --git a/config/config.json.default b/config/config.json.default index ce79140..53d59ac 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -22,6 +22,9 @@ "admin_messenger": { "auto_activate": true }, + "afk_plugin": { + "auto_activate": true + }, "announcer_plugin": { "auto_activate": true }, diff --git a/packets/packet_types.py b/packets/packet_types.py index b72a291..67f7097 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -129,7 +129,8 @@ def _decode(self, obj, context): connect_response = lambda name="connect_response": Struct(name, Flag("success"), VLQ("client_id"), - star_string("reject_reason")) + star_string("reject_reason"), + GreedyRange(star_string("celestial_info"))) # corrected. needs testing chat_received = lambda name="chat_received": Struct(name, @@ -265,6 +266,10 @@ def _decode(self, obj, context): String("entity", lambda ctx: ctx.entity_size), SignedVLQ("entity_id")))) +entity_update = lambda name="entity_update": Struct(name, + UBInt32("entity_id"), + StarByteArray("delta")) + client_context_update = lambda name="client_context": Struct(name, VLQ("length"), Byte("arguments"), diff --git a/plugins/afk_plugin/__init__.py b/plugins/afk_plugin/__init__.py new file mode 100644 index 0000000..07d17b0 --- /dev/null +++ b/plugins/afk_plugin/__init__.py @@ -0,0 +1 @@ +from afk_plugin import AFKCommand \ No newline at end of file diff --git a/plugins/afk_plugin/afk_plugin.py b/plugins/afk_plugin/afk_plugin.py new file mode 100644 index 0000000..eaa3d6a --- /dev/null +++ b/plugins/afk_plugin/afk_plugin.py @@ -0,0 +1,88 @@ +#=========================================================== +# afk_plugin +# Author: FZFalzar of Brutus.SG Starbound +# Version: v0.1 +# Description: Simple AFK command with configurable messages +#=========================================================== +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import permissions, UserLevels +from datetime import datetime + + +class AFKCommand(SimpleCommandPlugin): + name = "afk_plugin" + depends = ["command_dispatcher", "player_manager"] + commands = ["afk"] + auto_activate = True + afk_list = dict() + + def activate(self): + super(AFKCommand, self).activate() + self.player_manager = self.plugins["player_manager"].player_manager + self.load_config() + + def load_config(self): + try: + self.afk_message = self.config.plugin_config["afk_msg"] + self.afkreturn_message = self.config.plugin_config["afkreturn_msg"] + except Exception as e: + self.logger.info("Error occured! %s" % e) + if self.protocol is not None: + self.protocol.send_chat_message("Reload failed! Please check config.json!") + self.protocol.send_chat_message("Initiating with default values...") + self.afk_message = "^gray;is now AFK." + self.afkreturn_message = "^gray;has returned." + + @permissions(UserLevels.GUEST) + def afk(self, data): + """Marks a user as AFK (Away From Keyboard)\nSyntax: /afk""" + if self.protocol.player.name in self.afk_list: + if self.afk_list[self.protocol.player.name] == True: + self.unset_afk_status(self.protocol.player.name) + else: + self.set_afk_status(self.protocol.player.name) + else: + self.set_afk_status(self.protocol.player.name) + + def set_afk_status(self, name): + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^gray;<" + now.strftime("%H:%M") + "> " + else: + timestamp = "" + if name in self.afk_list: + if self.afk_list[name] == False: + self.factory.broadcast(timestamp + "%s ^gray;%s" % (self.player_manager.get_by_name(name).colored_name(self.config.colors), self.afk_message)) + self.afk_list[name] = True + else: + self.afk_list[name] = True + self.set_afk_status(name) + + def unset_afk_status(self, name): + now = datetime.now() + if self.config.chattimestamps: + timestamp = "^gray;<" + now.strftime("%H:%M") + "> " + else: + timestamp = "" + if name in self.afk_list: + if self.afk_list[name] == True: + self.factory.broadcast(timestamp + "%s ^gray;%s" % (self.player_manager.get_by_name(name).colored_name(self.config.colors), self.afkreturn_message)) + self.afk_list[name] = False + else: + self.afk_list[name] = False + self.unset_afk_status(name) + + #if player disconnects, remove him from list! + def on_client_disconnect(self, player): + self.unset_afk_status(self.protocol.player.name) + self.afk_list.pop(self.protocol.player.name, None) + + #if player does any of these, unmark him from afk! + def on_chat_sent(self, data): + self.unset_afk_status(self.protocol.player.name) + + def on_entity_create(self, data): + self.unset_afk_status(self.protocol.player.name) + + def on_entity_interact(self, data): + self.unset_afk_status(self.protocol.player.name) diff --git a/server.py b/server.py index 146a12c..11a23ee 100644 --- a/server.py +++ b/server.py @@ -151,7 +151,8 @@ def string_received(self, packet): """ if 53 >= packet.id: # DEBUG - print all packet IDs going to client - # logger.info("From Client: %s", packet.id) + #if packet.id not in [14, 44, 46, 53]: + # logger.info("From Client: %s", packet.id) if self.handle_starbound_packets(packet): self.client_protocol.transport.write( packet.original_data) From 3f18a7af2c37c68649950753d11ae6b5259136d7 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 01:55:19 -0500 Subject: [PATCH 75/95] Added login_who back in. Works! :) --- config/config.json.default | 3 +++ plugins/loginwho_plugin/__init__.py | 1 + plugins/loginwho_plugin/loginwho_plugin.py | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 plugins/loginwho_plugin/__init__.py create mode 100644 plugins/loginwho_plugin/loginwho_plugin.py diff --git a/config/config.json.default b/config/config.json.default index 53d59ac..5ca4c0b 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -56,6 +56,9 @@ "port": 6667, "server": "irc.freenode.net" }, + "loginwho_plugin": { + "auto_activate": true + }, "mod_chatter": { "auto_activate": true }, diff --git a/plugins/loginwho_plugin/__init__.py b/plugins/loginwho_plugin/__init__.py new file mode 100644 index 0000000..1065951 --- /dev/null +++ b/plugins/loginwho_plugin/__init__.py @@ -0,0 +1 @@ +from loginwho_plugin import LoginWhoPlugin \ No newline at end of file diff --git a/plugins/loginwho_plugin/loginwho_plugin.py b/plugins/loginwho_plugin/loginwho_plugin.py new file mode 100644 index 0000000..f5a178f --- /dev/null +++ b/plugins/loginwho_plugin/loginwho_plugin.py @@ -0,0 +1,18 @@ +# -*- coding: UTF-8 -*- +from base_plugin import BasePlugin +from plugins.core.player_manager import permissions + +class LoginWhoPlugin(BasePlugin): + """ + Displays a /who upon login + """ + name = "loginwho_plugin" + depends = ["command_dispatcher", "user_management_commands"] + auto_activate = True + + def activate(self): + super(LoginWhoPlugin, self).activate() + self.user_commands = self.plugins['user_management_commands'] + + def after_connect_response(self, data): + self.user_commands.who(data) From 20cb4e6c75384597b49d328836d8ffa88d749e12 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 02:05:44 -0500 Subject: [PATCH 76/95] Readded planet_visitor_announcer. Brought it up to speed with the new warp packets. Eveything else worked. --- config/config.json.default | 3 +++ plugins/planet_visitor_announcer/__init__.py | 1 + .../planet_visitor_announcer.py | 23 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 plugins/planet_visitor_announcer/__init__.py create mode 100644 plugins/planet_visitor_announcer/planet_visitor_announcer.py diff --git a/config/config.json.default b/config/config.json.default index 5ca4c0b..34a5d45 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -182,6 +182,9 @@ "protected_planets": [ ] }, + "planet_visitor_announcer_plugin": { + "auto_activate": true + }, "player_manager": { "auto_activate": true, "name_removal_regexes": [ diff --git a/plugins/planet_visitor_announcer/__init__.py b/plugins/planet_visitor_announcer/__init__.py new file mode 100644 index 0000000..8cdca43 --- /dev/null +++ b/plugins/planet_visitor_announcer/__init__.py @@ -0,0 +1 @@ +from planet_visitor_announcer import PlanetVisitorAnnouncer \ No newline at end of file diff --git a/plugins/planet_visitor_announcer/planet_visitor_announcer.py b/plugins/planet_visitor_announcer/planet_visitor_announcer.py new file mode 100644 index 0000000..b32f616 --- /dev/null +++ b/plugins/planet_visitor_announcer/planet_visitor_announcer.py @@ -0,0 +1,23 @@ +from base_plugin import BasePlugin +from packets import player_warp +from twisted.internet import reactor + +class PlanetVisitorAnnouncer(BasePlugin): + """ + Broadcasts a message whenever a player beams down to a planet. + """ + name = "planet_visitor_announcer_plugin" + auto_activate = True + + def activate(self): + super(PlanetVisitorAnnouncer, self).activate() + + def after_player_warp(self, data): + w = player_warp().parse(data.data) + if w.warp_type == "WARP_TO_ORBITED_WORLD" or w.warp_type == "WARP_TO_HOME_WORLD": + reactor.callLater(1, self.announce_on_planet, self.protocol.player) + + def announce_on_planet(self, who_beamed): + self.factory.broadcast_planet("%s^green; beamed down to the planet" % who_beamed.colored_name(self.config.colors), planet=self.protocol.player.planet) + + From dddbde4cadf383b9044e57b091ff40bfc492fbf2 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 02:22:26 -0500 Subject: [PATCH 77/95] Added fuelgiver back in. Small text tweaks. --- config/config.json.default | 7 ++++- plugins/afk_plugin/afk_plugin.py | 2 +- plugins/fuelgiver/__init__.py | 1 + plugins/fuelgiver/fuelgiver_plugin.py | 37 +++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 plugins/fuelgiver/__init__.py create mode 100644 plugins/fuelgiver/fuelgiver_plugin.py diff --git a/config/config.json.default b/config/config.json.default index 34a5d45..4dabc7d 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -23,7 +23,9 @@ "auto_activate": true }, "afk_plugin": { - "auto_activate": true + "auto_activate": true, + "afk_message": "^gray;is now AFK.", + "afkreturn_message": "^gray;has returned." }, "announcer_plugin": { "auto_activate": true @@ -46,6 +48,9 @@ "emotes_plugin": { "auto_activate": true }, + "fuelgiver_plugin": { + "auto_activate": true + }, "irc": { "auto_activate": false, "bot_nickname": "StarryPyBot", diff --git a/plugins/afk_plugin/afk_plugin.py b/plugins/afk_plugin/afk_plugin.py index eaa3d6a..dfbe61d 100644 --- a/plugins/afk_plugin/afk_plugin.py +++ b/plugins/afk_plugin/afk_plugin.py @@ -26,7 +26,7 @@ def load_config(self): self.afk_message = self.config.plugin_config["afk_msg"] self.afkreturn_message = self.config.plugin_config["afkreturn_msg"] except Exception as e: - self.logger.info("Error occured! %s" % e) + self.logger.error("Error occured! %s", e) if self.protocol is not None: self.protocol.send_chat_message("Reload failed! Please check config.json!") self.protocol.send_chat_message("Initiating with default values...") diff --git a/plugins/fuelgiver/__init__.py b/plugins/fuelgiver/__init__.py new file mode 100644 index 0000000..f122379 --- /dev/null +++ b/plugins/fuelgiver/__init__.py @@ -0,0 +1 @@ +from fuelgiver_plugin import FuelGiver \ No newline at end of file diff --git a/plugins/fuelgiver/fuelgiver_plugin.py b/plugins/fuelgiver/fuelgiver_plugin.py new file mode 100644 index 0000000..2c3ae29 --- /dev/null +++ b/plugins/fuelgiver/fuelgiver_plugin.py @@ -0,0 +1,37 @@ +#Kamilion's Fuel Giver plugin (https://gist.github.com/kamilion/9150547) +from base_plugin import SimpleCommandPlugin +from utility_functions import give_item_to_player +from plugins.core.player_manager import permissions, UserLevels +from time import time + + +class FuelGiver(SimpleCommandPlugin): + """ + Courteously give players fuel once a day (for those who ask for it). + """ + name = "fuelgiver_plugin" + depends = ["command_dispatcher", "player_manager"] + commands = ["fuel"] + auto_activate = True + + def activate(self): + super(FuelGiver, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + + @permissions(UserLevels.GUEST) + def fuel(self, data): + """Gives you enough fuel to fill your ship's tank (once a day).\nSyntax: /fuel""" + try: + my_storage = self.protocol.player.storage + except AttributeError: + self.logger.warning("Tried to give item to non-existent protocol.") + return + if not 'last_given_fuel' in my_storage or float(my_storage['last_given_fuel']) <= float(time()) - 86400: + my_storage['last_given_fuel'] = str(time()) + give_item_to_player(self.protocol, "fillerup", 1) + self.protocol.player.storage = my_storage + self.protocol.send_chat_message("You were given a daily fuel supply! Now go explore ;)") + self.logger.info("Gave fuel to %s.", self.protocol.player.name) + else: + self.protocol.send_chat_message("^red;No... -.- Go mining!") + From 9976a481a07c8a301831e1db2efd3bcf44d32e2a Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 02:30:35 -0500 Subject: [PATCH 78/95] Fixed shutdown command to not throw an error on no input. --- plugins/core/admin_commands_plugin/admin_command_plugin.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/core/admin_commands_plugin/admin_command_plugin.py b/plugins/core/admin_commands_plugin/admin_command_plugin.py index 6de1364..0be65b0 100644 --- a/plugins/core/admin_commands_plugin/admin_command_plugin.py +++ b/plugins/core/admin_commands_plugin/admin_command_plugin.py @@ -333,6 +333,9 @@ def passthrough(self, data): @permissions(UserLevels.ADMIN) def shutdown(self, data): """Shutdown the server in n seconds.\nSyntax: /shutdown (seconds) (>0)""" + if len(data) == 0: + self.protocol.send_chat_message(self.shutdown.__doc__) + return try: x = float(data[0]) except ValueError: From 93cb4d83fb4f02f78d6c1dc36269959caa9d3bb2 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 02:51:11 -0500 Subject: [PATCH 79/95] Added stateritems plugin back in. Works. --- config/config.json.default | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 4dabc7d..744ad7d 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -23,9 +23,9 @@ "auto_activate": true }, "afk_plugin": { - "auto_activate": true, "afk_message": "^gray;is now AFK.", - "afkreturn_message": "^gray;has returned." + "afkreturn_message": "^gray;has returned.", + "auto_activate": true }, "announcer_plugin": { "auto_activate": true @@ -49,7 +49,7 @@ "auto_activate": true }, "fuelgiver_plugin": { - "auto_activate": true + "auto_activate": false }, "irc": { "auto_activate": false, @@ -75,7 +75,7 @@ "auto_activate": true }, "new_player_greeter_plugin": { - "auto_activate": true, + "auto_activate": false, "items": [ [ "coalore", @@ -209,6 +209,16 @@ "starbound_config_manager": { "auto_activate": true }, + "starteritems_plugin": { + "auto_activate": false, + "message": "Enjoy these gifts from us!", + "items": [ + [ + "coalore", + 200 + ] + ] + }, "uptime_plugin": { "auto_activate": true }, From 7eb08f2bbcabd3daf8060e3d0790c37624b72937 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 14:06:19 -0500 Subject: [PATCH 80/95] Added claims and web_gui. Teihoo did the testing. :) --- .../a87d5e4bfa6fabc4deea7ddd50fb6e99.json | 1 - config/config.json.default | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) delete mode 100644 config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json diff --git a/config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json b/config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json deleted file mode 100644 index afec3fd..0000000 --- a/config/bookmarks/a87d5e4bfa6fabc4deea7ddd50fb6e99.json +++ /dev/null @@ -1 +0,0 @@ -[["-30562840:658406569:-263745435:4:0", "forest"], ["-30562840:658406569:-263745435:3:6", "spawn"]] \ No newline at end of file diff --git a/config/config.json.default b/config/config.json.default index 744ad7d..90b2d88 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -1,7 +1,7 @@ { "bind_address": "", "bind_port": 21025, - "chat_prefix": "@", + "chat_prefix": "#", "chattimestamps": true, "colors": { "admin": "^#C443F7;", @@ -23,8 +23,8 @@ "auto_activate": true }, "afk_plugin": { - "afk_message": "^gray;is now AFK.", - "afkreturn_message": "^gray;has returned.", + "afk_msg": "^gray;is now AFK.", + "afkreturn_msg": "^gray;has returned.", "auto_activate": true }, "announcer_plugin": { @@ -39,6 +39,11 @@ "chat_logger": { "auto_activate": true }, + "claims": { + "auto_activate": true, + "max_claims": 5, + "unclaimable_planets": [] + }, "colored_names_plugin": { "auto_activate": true }, @@ -86,7 +91,6 @@ }, "planet_protect": { "auto_activate": true, - "protect_everything": false, "bad_packets": [ "CONNECT_WIRE", "DISCONNECT_ALL_WIRES", @@ -184,6 +188,7 @@ ], "player_planets": { }, + "protect_everything": false, "protected_planets": [ ] }, @@ -227,6 +232,16 @@ }, "warpy_plugin": { "auto_activate": true + }, + "web_gui": { + "auto_activate": true, + "cookie_token": "", + "log_path": "webgui.log", + "log_path_access": "webgui_access.log", + "ownerpassword": "--ADD PASSWORD--", + "port": 8083, + "remember_cookie_token": true, + "restart_script": "" } }, "plugin_path": "plugins", From f2f1c6588a46acb3ca57496574cfb54a45bf7595 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Wed, 4 Feb 2015 14:17:22 -0500 Subject: [PATCH 81/95] Fixed my flub... --- config/bookmarks/bookmark_store | 1 + plugins/claims/__init__.py | 1 + plugins/claims/claims_plugin.py | 239 + plugins/web_gui/__init__.py | 1 + plugins/web_gui/static/adminstop.html | 37 + plugins/web_gui/static/ajax/dashboard.html | 92 + plugins/web_gui/static/ajax/playeredit.html | 93 + plugins/web_gui/static/ajax/playerlist.html | 37 + .../web_gui/static/ajax/playerlistonline.html | 36 + .../web_gui/static/ajax/playerquickmenu.html | 10 + .../web_gui/static/ajax/playersonline.html | 3 + .../web_gui/static/css/bootstrap-sortable.css | 84 + plugins/web_gui/static/css/footer.css | 6 + plugins/web_gui/static/css/style.min.css | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes plugins/web_gui/static/images/bg.jpg | Bin 0 -> 471 bytes plugins/web_gui/static/images/bullet.gif | Bin 0 -> 281 bytes plugins/web_gui/static/images/clock.gif | Bin 0 -> 272 bytes plugins/web_gui/static/images/comment.gif | Bin 0 -> 364 bytes plugins/web_gui/static/images/favicon.ico | Bin 0 -> 1150 bytes plugins/web_gui/static/images/gradientbg.jpg | Bin 0 -> 337 bytes plugins/web_gui/static/images/page.gif | Bin 0 -> 393 bytes plugins/web_gui/static/img/chevron-left.png | Bin 0 -> 1368 bytes plugins/web_gui/static/img/chevron-right.png | Bin 0 -> 1442 bytes .../web_gui/static/img/devoops_getdata.gif | Bin 0 -> 2892 bytes .../static/img/devoops_pattern_b10.png | Bin 0 -> 10010 bytes plugins/web_gui/static/img/logo-200.png | Bin 0 -> 2872 bytes plugins/web_gui/static/img/logo.png | Bin 0 -> 1168 bytes plugins/web_gui/static/img/sort-asc.png | Bin 0 -> 1022 bytes plugins/web_gui/static/img/sort-desc.png | Bin 0 -> 1017 bytes plugins/web_gui/static/img/sort.png | Bin 0 -> 1060 bytes plugins/web_gui/static/img/times.png | Bin 0 -> 1428 bytes .../web_gui/static/img/ui-accordion-down.png | Bin 0 -> 1125 bytes .../web_gui/static/img/ui-accordion-right.png | Bin 0 -> 1107 bytes plugins/web_gui/static/img/ui-left.png | Bin 0 -> 1085 bytes plugins/web_gui/static/img/ui-right.png | Bin 0 -> 1104 bytes plugins/web_gui/static/index.html | 126 + .../web_gui/static/js/bootstrap-sortable.js | 129 + plugins/web_gui/static/js/devoops.min.js | 1 + plugins/web_gui/static/js/noty/jquery.noty.js | 488 + .../web_gui/static/js/noty/layouts/bottom.js | 34 + .../static/js/noty/layouts/bottomCenter.js | 41 + .../static/js/noty/layouts/bottomLeft.js | 43 + .../static/js/noty/layouts/bottomRight.js | 43 + .../web_gui/static/js/noty/layouts/center.js | 56 + .../static/js/noty/layouts/centerLeft.js | 61 + .../static/js/noty/layouts/centerRight.js | 61 + .../web_gui/static/js/noty/layouts/inline.js | 31 + plugins/web_gui/static/js/noty/layouts/top.js | 34 + .../static/js/noty/layouts/topCenter.js | 41 + .../web_gui/static/js/noty/layouts/topLeft.js | 43 + .../static/js/noty/layouts/topRight.js | 43 + .../js/noty/packaged/jquery.noty.packaged.js | 1180 ++ .../noty/packaged/jquery.noty.packaged.min.js | 1 + plugins/web_gui/static/js/noty/promise.js | 432 + .../web_gui/static/js/noty/themes/default.js | 156 + plugins/web_gui/static/js/webgui.chat.js | 62 + plugins/web_gui/static/js/webgui.general.js | 109 + plugins/web_gui/static/login.html | 49 + .../plugins/bootstrap/bootstrap-theme.css | 347 + .../plugins/bootstrap/bootstrap-theme.css.map | 1 + .../plugins/bootstrap/bootstrap-theme.min.css | 7 + .../static/plugins/bootstrap/bootstrap.css | 5831 ++++++ .../plugins/bootstrap/bootstrap.css.map | 1 + .../static/plugins/bootstrap/bootstrap.js | 1951 ++ .../plugins/bootstrap/bootstrap.min.css | 7 + .../static/plugins/bootstrap/bootstrap.min.js | 6 + .../bootstrapvalidator/bootstrapValidator.css | 11 + .../bootstrapvalidator/bootstrapValidator.js | 849 + .../bootstrapValidator.min.css | 12 + .../bootstrapValidator.min.js | 11 + .../bootstrapValidator.scss | 15 + plugins/web_gui/static/plugins/d3/LICENSE | 26 + plugins/web_gui/static/plugins/d3/d3.v3.js | 9274 ++++++++++ .../web_gui/static/plugins/d3/d3.v3.min.js | 5 + .../static/plugins/datatables/TableTools.js | 2475 +++ .../plugins/datatables/TableTools_orig.js | 2475 +++ .../plugins/datatables/ZeroClipboard.js | 367 + .../plugins/datatables/copy_csv_xls_pdf.swf | Bin 0 -> 58827 bytes .../datatables/dataTables.bootstrap.js | 148 + .../plugins/datatables/jquery.dataTables.js | 12099 +++++++++++++ .../web_gui/static/plugins/fancybox/blank.gif | Bin 0 -> 43 bytes .../plugins/fancybox/fancybox_loading.gif | Bin 0 -> 6567 bytes .../plugins/fancybox/fancybox_loading@2x.gif | Bin 0 -> 13984 bytes .../plugins/fancybox/fancybox_overlay.png | Bin 0 -> 1003 bytes .../plugins/fancybox/fancybox_sprite.png | Bin 0 -> 1362 bytes .../plugins/fancybox/fancybox_sprite@2x.png | Bin 0 -> 6553 bytes .../fancybox/helpers/fancybox_buttons.png | Bin 0 -> 1080 bytes .../helpers/jquery.fancybox-buttons.css | 97 + .../helpers/jquery.fancybox-buttons.js | 122 + .../fancybox/helpers/jquery.fancybox-media.js | 199 + .../helpers/jquery.fancybox-thumbs.css | 55 + .../helpers/jquery.fancybox-thumbs.js | 162 + .../plugins/fancybox/jquery.fancybox.css | 274 + .../plugins/fancybox/jquery.fancybox.js | 2020 +++ .../plugins/fancybox/jquery.fancybox.pack.js | 46 + .../static/plugins/fineuploader/LICENSE | 676 + .../static/plugins/fineuploader/edit.gif | Bin 0 -> 145 bytes .../fineuploader/fineuploader-4.3.1.css | 205 + .../fineuploader/fineuploader-4.3.1.min.css | 19 + .../fineuploader/iframe.xss.response-4.3.1.js | 7 + .../fineuploader/jquery.fineuploader-4.3.1.js | 9228 ++++++++++ .../jquery.fineuploader-4.3.1.min.js | 20 + .../static/plugins/fineuploader/loading.gif | Bin 0 -> 1688 bytes .../plugins/fineuploader/processing.gif | Bin 0 -> 3209 bytes .../web_gui/static/plugins/flot/LICENSE.txt | 22 + .../static/plugins/flot/jquery.flot.js | 3137 ++++ .../static/plugins/flot/jquery.flot.resize.js | 60 + .../static/plugins/flot/jquery.flot.time.js | 431 + .../plugins/fullcalendar/fullcalendar.css | 601 + .../plugins/fullcalendar/fullcalendar.js | 6934 +++++++ .../plugins/fullcalendar/fullcalendar.min.js | 7 + .../fullcalendar/fullcalendar.print.css | 32 + .../static/plugins/fullcalendar/gcal.js | 100 + .../static/plugins/fullcalendar/lang/all.js | 3 + .../static/plugins/fullcalendar/lang/ar-ma.js | 1 + .../static/plugins/fullcalendar/lang/ar.js | 1 + .../static/plugins/fullcalendar/lang/bg.js | 1 + .../static/plugins/fullcalendar/lang/ca.js | 1 + .../static/plugins/fullcalendar/lang/cs.js | 1 + .../static/plugins/fullcalendar/lang/da.js | 1 + .../static/plugins/fullcalendar/lang/de.js | 1 + .../static/plugins/fullcalendar/lang/el.js | 1 + .../static/plugins/fullcalendar/lang/en-au.js | 1 + .../static/plugins/fullcalendar/lang/en-ca.js | 1 + .../static/plugins/fullcalendar/lang/en-gb.js | 1 + .../static/plugins/fullcalendar/lang/es.js | 1 + .../static/plugins/fullcalendar/lang/fa.js | 1 + .../static/plugins/fullcalendar/lang/fi.js | 1 + .../static/plugins/fullcalendar/lang/fr-ca.js | 1 + .../static/plugins/fullcalendar/lang/fr.js | 1 + .../static/plugins/fullcalendar/lang/hi.js | 1 + .../static/plugins/fullcalendar/lang/hr.js | 1 + .../static/plugins/fullcalendar/lang/hu.js | 1 + .../static/plugins/fullcalendar/lang/it.js | 1 + .../static/plugins/fullcalendar/lang/ja.js | 1 + .../static/plugins/fullcalendar/lang/ko.js | 1 + .../static/plugins/fullcalendar/lang/lt.js | 1 + .../static/plugins/fullcalendar/lang/lv.js | 1 + .../static/plugins/fullcalendar/lang/nl.js | 1 + .../static/plugins/fullcalendar/lang/pl.js | 1 + .../static/plugins/fullcalendar/lang/pt-br.js | 1 + .../static/plugins/fullcalendar/lang/pt.js | 1 + .../static/plugins/fullcalendar/lang/ro.js | 1 + .../static/plugins/fullcalendar/lang/ru.js | 1 + .../static/plugins/fullcalendar/lang/sk.js | 1 + .../static/plugins/fullcalendar/lang/sl.js | 1 + .../static/plugins/fullcalendar/lang/sv.js | 1 + .../static/plugins/fullcalendar/lang/th.js | 1 + .../static/plugins/fullcalendar/lang/tr.js | 1 + .../static/plugins/fullcalendar/lang/uk.js | 1 + .../static/plugins/fullcalendar/lang/zh-cn.js | 1 + .../static/plugins/fullcalendar/lang/zh-tw.js | 1 + .../static/plugins/jQuery-Knob/LICENSE | 20 + .../static/plugins/jQuery-Knob/jquery.knob.js | 766 + .../jquery-ui-timepicker-addon/LICENSE-MIT | 22 + .../i18n/jquery-ui-timepicker-af.js | 21 + .../i18n/jquery-ui-timepicker-am.js | 21 + .../i18n/jquery-ui-timepicker-bg.js | 21 + .../i18n/jquery-ui-timepicker-ca.js | 21 + .../i18n/jquery-ui-timepicker-cs.js | 21 + .../i18n/jquery-ui-timepicker-da.js | 21 + .../i18n/jquery-ui-timepicker-de.js | 21 + .../i18n/jquery-ui-timepicker-el.js | 21 + .../i18n/jquery-ui-timepicker-es.js | 21 + .../i18n/jquery-ui-timepicker-et.js | 21 + .../i18n/jquery-ui-timepicker-eu.js | 21 + .../i18n/jquery-ui-timepicker-fi.js | 21 + .../i18n/jquery-ui-timepicker-fr.js | 21 + .../i18n/jquery-ui-timepicker-gl.js | 21 + .../i18n/jquery-ui-timepicker-he.js | 21 + .../i18n/jquery-ui-timepicker-hr.js | 21 + .../i18n/jquery-ui-timepicker-hu.js | 21 + .../i18n/jquery-ui-timepicker-id.js | 21 + .../i18n/jquery-ui-timepicker-it.js | 21 + .../i18n/jquery-ui-timepicker-ja.js | 21 + .../i18n/jquery-ui-timepicker-ko.js | 21 + .../i18n/jquery-ui-timepicker-lt.js | 21 + .../i18n/jquery-ui-timepicker-nl.js | 21 + .../i18n/jquery-ui-timepicker-no.js | 21 + .../i18n/jquery-ui-timepicker-pl.js | 21 + .../i18n/jquery-ui-timepicker-pt-BR.js | 21 + .../i18n/jquery-ui-timepicker-pt.js | 21 + .../i18n/jquery-ui-timepicker-ro.js | 21 + .../i18n/jquery-ui-timepicker-ru.js | 21 + .../i18n/jquery-ui-timepicker-sk.js | 21 + .../i18n/jquery-ui-timepicker-sr-RS.js | 21 + .../i18n/jquery-ui-timepicker-sr-YU.js | 21 + .../i18n/jquery-ui-timepicker-sv.js | 21 + .../i18n/jquery-ui-timepicker-th.js | 18 + .../i18n/jquery-ui-timepicker-tr.js | 21 + .../i18n/jquery-ui-timepicker-uk.js | 21 + .../i18n/jquery-ui-timepicker-vi.js | 21 + .../i18n/jquery-ui-timepicker-zh-CN.js | 21 + .../i18n/jquery-ui-timepicker-zh-TW.js | 21 + .../jquery-ui-timepicker-addon/index.html | 971 + .../jquery-ui-sliderAccess.js | 91 + .../jquery-ui-timepicker-addon.css | 11 + .../jquery-ui-timepicker-addon.js | 2145 +++ .../jquery-ui-timepicker-addon.min.css | 5 + .../jquery-ui-timepicker-addon.min.js | 5 + .../jquery-ui/i18n/jquery-ui-i18n.min.js | 6 + .../i18n/jquery.ui.datepicker-af.min.js | 4 + .../i18n/jquery.ui.datepicker-ar-DZ.min.js | 4 + .../i18n/jquery.ui.datepicker-ar.min.js | 4 + .../i18n/jquery.ui.datepicker-az.min.js | 4 + .../i18n/jquery.ui.datepicker-be.min.js | 4 + .../i18n/jquery.ui.datepicker-bg.min.js | 4 + .../i18n/jquery.ui.datepicker-bs.min.js | 4 + .../i18n/jquery.ui.datepicker-ca.min.js | 4 + .../i18n/jquery.ui.datepicker-cs.min.js | 4 + .../i18n/jquery.ui.datepicker-cy-GB.min.js | 4 + .../i18n/jquery.ui.datepicker-da.min.js | 4 + .../i18n/jquery.ui.datepicker-de.min.js | 4 + .../i18n/jquery.ui.datepicker-el.min.js | 4 + .../i18n/jquery.ui.datepicker-en-AU.min.js | 4 + .../i18n/jquery.ui.datepicker-en-GB.min.js | 4 + .../i18n/jquery.ui.datepicker-en-NZ.min.js | 4 + .../i18n/jquery.ui.datepicker-eo.min.js | 4 + .../i18n/jquery.ui.datepicker-es.min.js | 4 + .../i18n/jquery.ui.datepicker-et.min.js | 4 + .../i18n/jquery.ui.datepicker-eu.min.js | 4 + .../i18n/jquery.ui.datepicker-fa.min.js | 4 + .../i18n/jquery.ui.datepicker-fi.min.js | 4 + .../i18n/jquery.ui.datepicker-fo.min.js | 4 + .../i18n/jquery.ui.datepicker-fr-CA.min.js | 4 + .../i18n/jquery.ui.datepicker-fr-CH.min.js | 4 + .../i18n/jquery.ui.datepicker-fr.min.js | 4 + .../i18n/jquery.ui.datepicker-gl.min.js | 4 + .../i18n/jquery.ui.datepicker-he.min.js | 4 + .../i18n/jquery.ui.datepicker-hi.min.js | 4 + .../i18n/jquery.ui.datepicker-hr.min.js | 4 + .../i18n/jquery.ui.datepicker-hu.min.js | 4 + .../i18n/jquery.ui.datepicker-hy.min.js | 4 + .../i18n/jquery.ui.datepicker-id.min.js | 4 + .../i18n/jquery.ui.datepicker-is.min.js | 4 + .../i18n/jquery.ui.datepicker-it.min.js | 4 + .../i18n/jquery.ui.datepicker-ja.min.js | 4 + .../i18n/jquery.ui.datepicker-ka.min.js | 4 + .../i18n/jquery.ui.datepicker-kk.min.js | 4 + .../i18n/jquery.ui.datepicker-km.min.js | 4 + .../i18n/jquery.ui.datepicker-ko.min.js | 4 + .../i18n/jquery.ui.datepicker-ky.min.js | 4 + .../i18n/jquery.ui.datepicker-lb.min.js | 4 + .../i18n/jquery.ui.datepicker-lt.min.js | 4 + .../i18n/jquery.ui.datepicker-lv.min.js | 4 + .../i18n/jquery.ui.datepicker-mk.min.js | 4 + .../i18n/jquery.ui.datepicker-ml.min.js | 4 + .../i18n/jquery.ui.datepicker-ms.min.js | 4 + .../i18n/jquery.ui.datepicker-nb.min.js | 4 + .../i18n/jquery.ui.datepicker-nl-BE.min.js | 4 + .../i18n/jquery.ui.datepicker-nl.min.js | 4 + .../i18n/jquery.ui.datepicker-nn.min.js | 4 + .../i18n/jquery.ui.datepicker-no.min.js | 4 + .../i18n/jquery.ui.datepicker-pl.min.js | 4 + .../i18n/jquery.ui.datepicker-pt-BR.min.js | 4 + .../i18n/jquery.ui.datepicker-pt.min.js | 4 + .../i18n/jquery.ui.datepicker-rm.min.js | 4 + .../i18n/jquery.ui.datepicker-ro.min.js | 4 + .../i18n/jquery.ui.datepicker-ru.min.js | 4 + .../i18n/jquery.ui.datepicker-sk.min.js | 4 + .../i18n/jquery.ui.datepicker-sl.min.js | 4 + .../i18n/jquery.ui.datepicker-sq.min.js | 4 + .../i18n/jquery.ui.datepicker-sr-SR.min.js | 4 + .../i18n/jquery.ui.datepicker-sr.min.js | 4 + .../i18n/jquery.ui.datepicker-sv.min.js | 4 + .../i18n/jquery.ui.datepicker-ta.min.js | 4 + .../i18n/jquery.ui.datepicker-th.min.js | 4 + .../i18n/jquery.ui.datepicker-tj.min.js | 4 + .../i18n/jquery.ui.datepicker-tr.min.js | 4 + .../i18n/jquery.ui.datepicker-uk.min.js | 4 + .../i18n/jquery.ui.datepicker-vi.min.js | 4 + .../i18n/jquery.ui.datepicker-zh-CN.min.js | 4 + .../i18n/jquery.ui.datepicker-zh-HK.min.js | 4 + .../i18n/jquery.ui.datepicker-zh-TW.min.js | 4 + .../jquery-ui/images/animated-overlay.gif | Bin 0 -> 1738 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../static/plugins/jquery-ui/jquery-ui.css | 1189 ++ .../static/plugins/jquery-ui/jquery-ui.js | 15040 ++++++++++++++++ .../plugins/jquery-ui/jquery-ui.min.css | 4 + .../static/plugins/jquery-ui/jquery-ui.min.js | 12 + .../static/plugins/jquery/jquery-2.1.0.min.js | 4 + .../plugins/justified-gallery/README.md | 14 + .../jquery.justifiedgallery.css | 73 + .../jquery.justifiedgallery.js | 258 + .../jquery.justifiedgallery.min.css | 17 + .../jquery.justifiedgallery.min.js | 24 + .../plugins/justified-gallery/loading.gif | Bin 0 -> 9427 bytes plugins/web_gui/static/plugins/moment/LICENSE | 22 + .../web_gui/static/plugins/moment/langs.js | 5841 ++++++ .../static/plugins/moment/langs.min.js | 3 + .../plugins/moment/moment-with-langs.js | 7768 ++++++++ .../plugins/moment/moment-with-langs.min.js | 9 + .../static/plugins/moment/moment.min.js | 6 + .../web_gui/static/plugins/morris/morris.js | 1767 ++ .../static/plugins/morris/morris.min.js | 1 + .../static/plugins/raphael/raphael-min.js | 11 + .../web_gui/static/plugins/raphael/raphael.js | 8111 +++++++++ .../web_gui/static/plugins/select2/LICENSE | 18 + .../web_gui/static/plugins/select2/README.md | 83 + .../web_gui/static/plugins/select2/release.sh | 73 + .../plugins/select2/select2-bootstrap.css | 87 + .../plugins/select2/select2-spinner.gif | Bin 0 -> 1849 bytes .../static/plugins/select2/select2.css | 615 + .../web_gui/static/plugins/select2/select2.js | 3255 ++++ .../static/plugins/select2/select2.min.js | 22 + .../static/plugins/select2/select2.png | Bin 0 -> 613 bytes .../plugins/select2/select2_locale_ar.js | 17 + .../plugins/select2/select2_locale_bg.js | 17 + .../plugins/select2/select2_locale_ca.js | 17 + .../plugins/select2/select2_locale_cs.js | 49 + .../plugins/select2/select2_locale_da.js | 17 + .../plugins/select2/select2_locale_de.js | 15 + .../plugins/select2/select2_locale_el.js | 17 + .../select2/select2_locale_en.js.template | 17 + .../plugins/select2/select2_locale_es.js | 15 + .../plugins/select2/select2_locale_et.js | 17 + .../plugins/select2/select2_locale_eu.js | 43 + .../plugins/select2/select2_locale_fa.js | 17 + .../plugins/select2/select2_locale_fi.js | 28 + .../plugins/select2/select2_locale_fr.js | 15 + .../plugins/select2/select2_locale_gl.js | 43 + .../plugins/select2/select2_locale_he.js | 17 + .../plugins/select2/select2_locale_hr.js | 42 + .../plugins/select2/select2_locale_hu.js | 15 + .../plugins/select2/select2_locale_id.js | 17 + .../plugins/select2/select2_locale_is.js | 16 + .../plugins/select2/select2_locale_it.js | 15 + .../plugins/select2/select2_locale_ja.js | 15 + .../plugins/select2/select2_locale_ko.js | 17 + .../plugins/select2/select2_locale_lt.js | 29 + .../plugins/select2/select2_locale_lv.js | 16 + .../plugins/select2/select2_locale_mk.js | 17 + .../plugins/select2/select2_locale_ms.js | 17 + .../plugins/select2/select2_locale_nl.js | 15 + .../plugins/select2/select2_locale_no.js | 18 + .../plugins/select2/select2_locale_pl.js | 37 + .../plugins/select2/select2_locale_pt-BR.js | 15 + .../plugins/select2/select2_locale_pt-PT.js | 15 + .../plugins/select2/select2_locale_ro.js | 15 + .../plugins/select2/select2_locale_ru.js | 15 + .../plugins/select2/select2_locale_sk.js | 48 + .../plugins/select2/select2_locale_sv.js | 17 + .../plugins/select2/select2_locale_th.js | 17 + .../plugins/select2/select2_locale_tr.js | 17 + .../plugins/select2/select2_locale_ua.js | 17 + .../plugins/select2/select2_locale_vi.js | 18 + .../plugins/select2/select2_locale_zh-CN.js | 14 + .../plugins/select2/select2_locale_zh-TW.js | 14 + .../static/plugins/select2/select2x2.png | Bin 0 -> 845 bytes .../plugins/sparkline/jquery.sparkline.js | 3054 ++++ .../plugins/sparkline/jquery.sparkline.min.js | 5 + .../plugins/tinymce/jquery.tinymce.min.js | 1 + .../static/plugins/tinymce/langs/readme.md | 3 + .../static/plugins/tinymce/license.txt | 504 + .../tinymce/plugins/advlist/plugin.min.js | 1 + .../tinymce/plugins/anchor/plugin.min.js | 1 + .../tinymce/plugins/autolink/plugin.min.js | 1 + .../tinymce/plugins/autoresize/plugin.min.js | 1 + .../tinymce/plugins/autosave/plugin.min.js | 1 + .../tinymce/plugins/bbcode/plugin.min.js | 1 + .../tinymce/plugins/charmap/plugin.min.js | 1 + .../tinymce/plugins/code/plugin.min.js | 1 + .../tinymce/plugins/contextmenu/plugin.min.js | 1 + .../plugins/directionality/plugin.min.js | 1 + .../plugins/emoticons/img/smiley-cool.gif | Bin 0 -> 354 bytes .../plugins/emoticons/img/smiley-cry.gif | Bin 0 -> 329 bytes .../emoticons/img/smiley-embarassed.gif | Bin 0 -> 331 bytes .../emoticons/img/smiley-foot-in-mouth.gif | Bin 0 -> 342 bytes .../plugins/emoticons/img/smiley-frown.gif | Bin 0 -> 340 bytes .../plugins/emoticons/img/smiley-innocent.gif | Bin 0 -> 336 bytes .../plugins/emoticons/img/smiley-kiss.gif | Bin 0 -> 338 bytes .../plugins/emoticons/img/smiley-laughing.gif | Bin 0 -> 343 bytes .../emoticons/img/smiley-money-mouth.gif | Bin 0 -> 321 bytes .../plugins/emoticons/img/smiley-sealed.gif | Bin 0 -> 323 bytes .../plugins/emoticons/img/smiley-smile.gif | Bin 0 -> 344 bytes .../emoticons/img/smiley-surprised.gif | Bin 0 -> 338 bytes .../emoticons/img/smiley-tongue-out.gif | Bin 0 -> 328 bytes .../emoticons/img/smiley-undecided.gif | Bin 0 -> 337 bytes .../plugins/emoticons/img/smiley-wink.gif | Bin 0 -> 350 bytes .../plugins/emoticons/img/smiley-yell.gif | Bin 0 -> 336 bytes .../tinymce/plugins/emoticons/plugin.min.js | 1 + .../tinymce/plugins/example/plugin.min.js | 1 + .../plugins/example_dependency/plugin.min.js | 1 + .../tinymce/plugins/fullpage/plugin.min.js | 1 + .../tinymce/plugins/fullscreen/plugin.min.js | 1 + .../plugins/tinymce/plugins/hr/plugin.min.js | 1 + .../tinymce/plugins/image/plugin.min.js | 1 + .../tinymce/plugins/importcss/plugin.min.js | 1 + .../plugins/insertdatetime/plugin.min.js | 1 + .../tinymce/plugins/layer/plugin.min.js | 1 + .../plugins/legacyoutput/plugin.min.js | 1 + .../tinymce/plugins/link/plugin.min.js | 1 + .../tinymce/plugins/lists/plugin.min.js | 1 + .../tinymce/plugins/media/moxieplayer.swf | Bin 0 -> 20017 bytes .../tinymce/plugins/media/plugin.min.js | 1 + .../tinymce/plugins/nonbreaking/plugin.min.js | 1 + .../tinymce/plugins/noneditable/plugin.min.js | 1 + .../tinymce/plugins/pagebreak/plugin.min.js | 1 + .../tinymce/plugins/paste/plugin.min.js | 1 + .../tinymce/plugins/preview/plugin.min.js | 1 + .../tinymce/plugins/print/plugin.min.js | 1 + .../tinymce/plugins/save/plugin.min.js | 1 + .../plugins/searchreplace/plugin.min.js | 1 + .../plugins/spellchecker/plugin.min.js | 1 + .../tinymce/plugins/tabfocus/plugin.min.js | 1 + .../tinymce/plugins/table/plugin.min.js | 1 + .../tinymce/plugins/template/plugin.min.js | 1 + .../tinymce/plugins/textcolor/plugin.min.js | 1 + .../plugins/visualblocks/css/visualblocks.css | 128 + .../plugins/visualblocks/plugin.min.js | 1 + .../tinymce/plugins/visualchars/plugin.min.js | 1 + .../tinymce/plugins/wordcount/plugin.min.js | 1 + .../skins/lightgray/content.inline.min.css | 1 + .../tinymce/skins/lightgray/content.min.css | 1 + .../tinymce/skins/lightgray/fonts/readme.md | 1 + .../skins/lightgray/fonts/tinymce-small.eot | Bin 0 -> 8348 bytes .../skins/lightgray/fonts/tinymce-small.svg | 175 + .../skins/lightgray/fonts/tinymce-small.ttf | Bin 0 -> 8164 bytes .../skins/lightgray/fonts/tinymce-small.woff | Bin 0 -> 8340 bytes .../tinymce/skins/lightgray/fonts/tinymce.eot | Bin 0 -> 8276 bytes .../tinymce/skins/lightgray/fonts/tinymce.svg | 153 + .../tinymce/skins/lightgray/fonts/tinymce.ttf | Bin 0 -> 8112 bytes .../skins/lightgray/fonts/tinymce.woff | Bin 0 -> 8408 bytes .../tinymce/skins/lightgray/img/anchor.gif | Bin 0 -> 53 bytes .../tinymce/skins/lightgray/img/loader.gif | Bin 0 -> 2608 bytes .../tinymce/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes .../tinymce/skins/lightgray/img/trans.gif | Bin 0 -> 43 bytes .../tinymce/skins/lightgray/skin.ie7.min.css | 1 + .../tinymce/skins/lightgray/skin.min.css | 1 + .../tinymce/themes/modern/theme.min.js | 1 + .../static/plugins/tinymce/tinymce.min.js | 9 + .../web_gui/static/plugins/xcharts/LICENSE | 7 + .../web_gui/static/plugins/xcharts/README.md | 17 + .../static/plugins/xcharts/xcharts.css | 283 + .../web_gui/static/plugins/xcharts/xcharts.js | 1158 ++ .../static/plugins/xcharts/xcharts.min.css | 1 + .../static/plugins/xcharts/xcharts.min.js | 5 + plugins/web_gui/static/restart.html | 37 + plugins/web_gui/web_gui.py | 325 + plugins/web_gui/web_gui_plugin.py | 88 + 456 files changed, 120892 insertions(+) create mode 100644 config/bookmarks/bookmark_store create mode 100644 plugins/claims/__init__.py create mode 100644 plugins/claims/claims_plugin.py create mode 100644 plugins/web_gui/__init__.py create mode 100644 plugins/web_gui/static/adminstop.html create mode 100644 plugins/web_gui/static/ajax/dashboard.html create mode 100644 plugins/web_gui/static/ajax/playeredit.html create mode 100644 plugins/web_gui/static/ajax/playerlist.html create mode 100644 plugins/web_gui/static/ajax/playerlistonline.html create mode 100644 plugins/web_gui/static/ajax/playerquickmenu.html create mode 100644 plugins/web_gui/static/ajax/playersonline.html create mode 100644 plugins/web_gui/static/css/bootstrap-sortable.css create mode 100644 plugins/web_gui/static/css/footer.css create mode 100644 plugins/web_gui/static/css/style.min.css create mode 100644 plugins/web_gui/static/fonts/glyphicons-halflings-regular.eot create mode 100644 plugins/web_gui/static/fonts/glyphicons-halflings-regular.svg create mode 100644 plugins/web_gui/static/fonts/glyphicons-halflings-regular.ttf create mode 100644 plugins/web_gui/static/fonts/glyphicons-halflings-regular.woff create mode 100644 plugins/web_gui/static/images/bg.jpg create mode 100644 plugins/web_gui/static/images/bullet.gif create mode 100644 plugins/web_gui/static/images/clock.gif create mode 100644 plugins/web_gui/static/images/comment.gif create mode 100644 plugins/web_gui/static/images/favicon.ico create mode 100644 plugins/web_gui/static/images/gradientbg.jpg create mode 100644 plugins/web_gui/static/images/page.gif create mode 100644 plugins/web_gui/static/img/chevron-left.png create mode 100644 plugins/web_gui/static/img/chevron-right.png create mode 100644 plugins/web_gui/static/img/devoops_getdata.gif create mode 100644 plugins/web_gui/static/img/devoops_pattern_b10.png create mode 100644 plugins/web_gui/static/img/logo-200.png create mode 100644 plugins/web_gui/static/img/logo.png create mode 100644 plugins/web_gui/static/img/sort-asc.png create mode 100644 plugins/web_gui/static/img/sort-desc.png create mode 100644 plugins/web_gui/static/img/sort.png create mode 100644 plugins/web_gui/static/img/times.png create mode 100644 plugins/web_gui/static/img/ui-accordion-down.png create mode 100644 plugins/web_gui/static/img/ui-accordion-right.png create mode 100644 plugins/web_gui/static/img/ui-left.png create mode 100644 plugins/web_gui/static/img/ui-right.png create mode 100644 plugins/web_gui/static/index.html create mode 100644 plugins/web_gui/static/js/bootstrap-sortable.js create mode 100644 plugins/web_gui/static/js/devoops.min.js create mode 100644 plugins/web_gui/static/js/noty/jquery.noty.js create mode 100644 plugins/web_gui/static/js/noty/layouts/bottom.js create mode 100644 plugins/web_gui/static/js/noty/layouts/bottomCenter.js create mode 100644 plugins/web_gui/static/js/noty/layouts/bottomLeft.js create mode 100644 plugins/web_gui/static/js/noty/layouts/bottomRight.js create mode 100644 plugins/web_gui/static/js/noty/layouts/center.js create mode 100644 plugins/web_gui/static/js/noty/layouts/centerLeft.js create mode 100644 plugins/web_gui/static/js/noty/layouts/centerRight.js create mode 100644 plugins/web_gui/static/js/noty/layouts/inline.js create mode 100644 plugins/web_gui/static/js/noty/layouts/top.js create mode 100644 plugins/web_gui/static/js/noty/layouts/topCenter.js create mode 100644 plugins/web_gui/static/js/noty/layouts/topLeft.js create mode 100644 plugins/web_gui/static/js/noty/layouts/topRight.js create mode 100644 plugins/web_gui/static/js/noty/packaged/jquery.noty.packaged.js create mode 100644 plugins/web_gui/static/js/noty/packaged/jquery.noty.packaged.min.js create mode 100644 plugins/web_gui/static/js/noty/promise.js create mode 100644 plugins/web_gui/static/js/noty/themes/default.js create mode 100644 plugins/web_gui/static/js/webgui.chat.js create mode 100644 plugins/web_gui/static/js/webgui.general.js create mode 100644 plugins/web_gui/static/login.html create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap-theme.css create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap-theme.css.map create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap-theme.min.css create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap.css create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap.css.map create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap.js create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap.min.css create mode 100644 plugins/web_gui/static/plugins/bootstrap/bootstrap.min.js create mode 100644 plugins/web_gui/static/plugins/bootstrapvalidator/bootstrapValidator.css create mode 100644 plugins/web_gui/static/plugins/bootstrapvalidator/bootstrapValidator.js create mode 100644 plugins/web_gui/static/plugins/bootstrapvalidator/bootstrapValidator.min.css create mode 100644 plugins/web_gui/static/plugins/bootstrapvalidator/bootstrapValidator.min.js create mode 100644 plugins/web_gui/static/plugins/bootstrapvalidator/bootstrapValidator.scss create mode 100644 plugins/web_gui/static/plugins/d3/LICENSE create mode 100644 plugins/web_gui/static/plugins/d3/d3.v3.js create mode 100644 plugins/web_gui/static/plugins/d3/d3.v3.min.js create mode 100644 plugins/web_gui/static/plugins/datatables/TableTools.js create mode 100644 plugins/web_gui/static/plugins/datatables/TableTools_orig.js create mode 100644 plugins/web_gui/static/plugins/datatables/ZeroClipboard.js create mode 100644 plugins/web_gui/static/plugins/datatables/copy_csv_xls_pdf.swf create mode 100644 plugins/web_gui/static/plugins/datatables/dataTables.bootstrap.js create mode 100644 plugins/web_gui/static/plugins/datatables/jquery.dataTables.js create mode 100644 plugins/web_gui/static/plugins/fancybox/blank.gif create mode 100644 plugins/web_gui/static/plugins/fancybox/fancybox_loading.gif create mode 100644 plugins/web_gui/static/plugins/fancybox/fancybox_loading@2x.gif create mode 100644 plugins/web_gui/static/plugins/fancybox/fancybox_overlay.png create mode 100644 plugins/web_gui/static/plugins/fancybox/fancybox_sprite.png create mode 100644 plugins/web_gui/static/plugins/fancybox/fancybox_sprite@2x.png create mode 100644 plugins/web_gui/static/plugins/fancybox/helpers/fancybox_buttons.png create mode 100644 plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.css create mode 100644 plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.js create mode 100644 plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-media.js create mode 100644 plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.css create mode 100644 plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.js create mode 100644 plugins/web_gui/static/plugins/fancybox/jquery.fancybox.css create mode 100644 plugins/web_gui/static/plugins/fancybox/jquery.fancybox.js create mode 100644 plugins/web_gui/static/plugins/fancybox/jquery.fancybox.pack.js create mode 100644 plugins/web_gui/static/plugins/fineuploader/LICENSE create mode 100644 plugins/web_gui/static/plugins/fineuploader/edit.gif create mode 100644 plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.css create mode 100644 plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.min.css create mode 100644 plugins/web_gui/static/plugins/fineuploader/iframe.xss.response-4.3.1.js create mode 100644 plugins/web_gui/static/plugins/fineuploader/jquery.fineuploader-4.3.1.js create mode 100644 plugins/web_gui/static/plugins/fineuploader/jquery.fineuploader-4.3.1.min.js create mode 100644 plugins/web_gui/static/plugins/fineuploader/loading.gif create mode 100644 plugins/web_gui/static/plugins/fineuploader/processing.gif create mode 100644 plugins/web_gui/static/plugins/flot/LICENSE.txt create mode 100644 plugins/web_gui/static/plugins/flot/jquery.flot.js create mode 100644 plugins/web_gui/static/plugins/flot/jquery.flot.resize.js create mode 100644 plugins/web_gui/static/plugins/flot/jquery.flot.time.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/fullcalendar.css create mode 100644 plugins/web_gui/static/plugins/fullcalendar/fullcalendar.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/fullcalendar.min.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/fullcalendar.print.css create mode 100644 plugins/web_gui/static/plugins/fullcalendar/gcal.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/all.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ar-ma.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ar.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/bg.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ca.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/cs.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/da.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/de.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/el.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/en-au.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/en-ca.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/en-gb.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/es.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/fa.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/fi.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/fr-ca.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/fr.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/hi.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/hr.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/hu.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/it.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ja.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ko.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/lt.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/lv.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/nl.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/pl.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/pt-br.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/pt.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ro.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/ru.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/sk.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/sl.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/sv.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/th.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/tr.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/uk.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/zh-cn.js create mode 100644 plugins/web_gui/static/plugins/fullcalendar/lang/zh-tw.js create mode 100644 plugins/web_gui/static/plugins/jQuery-Knob/LICENSE create mode 100644 plugins/web_gui/static/plugins/jQuery-Knob/jquery.knob.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/LICENSE-MIT create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-af.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-am.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-bg.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-ca.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-cs.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-da.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-de.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-el.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-es.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-et.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-eu.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-fi.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-fr.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-gl.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-he.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-hr.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-hu.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-id.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-it.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-ja.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-ko.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-lt.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-nl.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-no.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-pl.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-pt-BR.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-pt.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-ro.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-ru.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-sk.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-sr-RS.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-sr-YU.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-sv.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-th.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-tr.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-uk.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-vi.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-zh-CN.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/i18n/jquery-ui-timepicker-zh-TW.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/index.html create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/jquery-ui-sliderAccess.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.css create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.min.css create mode 100644 plugins/web_gui/static/plugins/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery-ui-i18n.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-af.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ar-DZ.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ar.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-az.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-be.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-bg.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-bs.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ca.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-cs.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-cy-GB.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-da.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-de.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-el.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-en-AU.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-en-GB.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-en-NZ.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-eo.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-es.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-et.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-eu.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-fa.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-fi.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-fo.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-fr-CA.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-fr-CH.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-fr.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-gl.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-he.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-hi.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-hr.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-hu.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-hy.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-id.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-is.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-it.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ja.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ka.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-kk.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-km.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ko.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ky.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-lb.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-lt.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-lv.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-mk.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ml.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ms.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-nb.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-nl-BE.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-nl.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-nn.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-no.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-pl.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-pt-BR.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-pt.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-rm.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ro.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ru.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-sk.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-sl.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-sq.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-sr-SR.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-sr.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-sv.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-ta.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-th.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-tj.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-tr.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-uk.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-vi.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-zh-CN.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-zh-HK.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/i18n/jquery.ui.datepicker-zh-TW.min.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/animated-overlay.gif create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-icons_222222_256x240.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-icons_2e83ff_256x240.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-icons_454545_256x240.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-icons_888888_256x240.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/images/ui-icons_cd0a0a_256x240.png create mode 100644 plugins/web_gui/static/plugins/jquery-ui/jquery-ui.css create mode 100644 plugins/web_gui/static/plugins/jquery-ui/jquery-ui.js create mode 100644 plugins/web_gui/static/plugins/jquery-ui/jquery-ui.min.css create mode 100644 plugins/web_gui/static/plugins/jquery-ui/jquery-ui.min.js create mode 100644 plugins/web_gui/static/plugins/jquery/jquery-2.1.0.min.js create mode 100644 plugins/web_gui/static/plugins/justified-gallery/README.md create mode 100644 plugins/web_gui/static/plugins/justified-gallery/jquery.justifiedgallery.css create mode 100644 plugins/web_gui/static/plugins/justified-gallery/jquery.justifiedgallery.js create mode 100644 plugins/web_gui/static/plugins/justified-gallery/jquery.justifiedgallery.min.css create mode 100644 plugins/web_gui/static/plugins/justified-gallery/jquery.justifiedgallery.min.js create mode 100644 plugins/web_gui/static/plugins/justified-gallery/loading.gif create mode 100644 plugins/web_gui/static/plugins/moment/LICENSE create mode 100644 plugins/web_gui/static/plugins/moment/langs.js create mode 100644 plugins/web_gui/static/plugins/moment/langs.min.js create mode 100644 plugins/web_gui/static/plugins/moment/moment-with-langs.js create mode 100644 plugins/web_gui/static/plugins/moment/moment-with-langs.min.js create mode 100644 plugins/web_gui/static/plugins/moment/moment.min.js create mode 100644 plugins/web_gui/static/plugins/morris/morris.js create mode 100644 plugins/web_gui/static/plugins/morris/morris.min.js create mode 100644 plugins/web_gui/static/plugins/raphael/raphael-min.js create mode 100644 plugins/web_gui/static/plugins/raphael/raphael.js create mode 100644 plugins/web_gui/static/plugins/select2/LICENSE create mode 100644 plugins/web_gui/static/plugins/select2/README.md create mode 100644 plugins/web_gui/static/plugins/select2/release.sh create mode 100644 plugins/web_gui/static/plugins/select2/select2-bootstrap.css create mode 100644 plugins/web_gui/static/plugins/select2/select2-spinner.gif create mode 100644 plugins/web_gui/static/plugins/select2/select2.css create mode 100644 plugins/web_gui/static/plugins/select2/select2.js create mode 100644 plugins/web_gui/static/plugins/select2/select2.min.js create mode 100644 plugins/web_gui/static/plugins/select2/select2.png create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ar.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_bg.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ca.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_cs.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_da.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_de.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_el.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_en.js.template create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_es.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_et.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_eu.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_fa.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_fi.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_fr.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_gl.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_he.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_hr.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_hu.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_id.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_is.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_it.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ja.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ko.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_lt.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_lv.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_mk.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ms.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_nl.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_no.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_pl.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_pt-BR.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_pt-PT.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ro.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ru.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_sk.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_sv.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_th.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_tr.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_ua.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_vi.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_zh-CN.js create mode 100644 plugins/web_gui/static/plugins/select2/select2_locale_zh-TW.js create mode 100644 plugins/web_gui/static/plugins/select2/select2x2.png create mode 100644 plugins/web_gui/static/plugins/sparkline/jquery.sparkline.js create mode 100644 plugins/web_gui/static/plugins/sparkline/jquery.sparkline.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/jquery.tinymce.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/langs/readme.md create mode 100644 plugins/web_gui/static/plugins/tinymce/license.txt create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/advlist/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/anchor/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/autolink/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/autoresize/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/autosave/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/bbcode/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/charmap/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/code/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/contextmenu/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/directionality/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-cool.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-cry.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-embarassed.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-frown.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-innocent.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-kiss.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-laughing.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-money-mouth.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-sealed.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-smile.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-surprised.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-tongue-out.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-undecided.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-wink.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/img/smiley-yell.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/emoticons/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/example/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/example_dependency/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/fullpage/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/fullscreen/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/hr/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/image/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/importcss/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/insertdatetime/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/layer/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/legacyoutput/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/link/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/lists/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/media/moxieplayer.swf create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/media/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/nonbreaking/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/noneditable/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/pagebreak/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/paste/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/preview/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/print/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/save/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/searchreplace/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/spellchecker/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/tabfocus/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/table/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/template/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/textcolor/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/css/visualblocks.css create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/visualchars/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/plugins/wordcount/plugin.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.inline.min.css create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.min.css create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/readme.md create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.eot create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.svg create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.ttf create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.woff create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.eot create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.svg create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.ttf create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.woff create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/anchor.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/loader.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/object.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/trans.gif create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/skin.ie7.min.css create mode 100644 plugins/web_gui/static/plugins/tinymce/skins/lightgray/skin.min.css create mode 100644 plugins/web_gui/static/plugins/tinymce/themes/modern/theme.min.js create mode 100644 plugins/web_gui/static/plugins/tinymce/tinymce.min.js create mode 100644 plugins/web_gui/static/plugins/xcharts/LICENSE create mode 100644 plugins/web_gui/static/plugins/xcharts/README.md create mode 100644 plugins/web_gui/static/plugins/xcharts/xcharts.css create mode 100644 plugins/web_gui/static/plugins/xcharts/xcharts.js create mode 100644 plugins/web_gui/static/plugins/xcharts/xcharts.min.css create mode 100644 plugins/web_gui/static/plugins/xcharts/xcharts.min.js create mode 100644 plugins/web_gui/static/restart.html create mode 100644 plugins/web_gui/web_gui.py create mode 100644 plugins/web_gui/web_gui_plugin.py diff --git a/config/bookmarks/bookmark_store b/config/bookmarks/bookmark_store new file mode 100644 index 0000000..3b6be2b --- /dev/null +++ b/config/bookmarks/bookmark_store @@ -0,0 +1 @@ +Bookmarks and PoI's are stored in this folder. \ No newline at end of file diff --git a/plugins/claims/__init__.py b/plugins/claims/__init__.py new file mode 100644 index 0000000..4567aff --- /dev/null +++ b/plugins/claims/__init__.py @@ -0,0 +1 @@ +from claims_plugin import ClaimsPlugin diff --git a/plugins/claims/claims_plugin.py b/plugins/claims/claims_plugin.py new file mode 100644 index 0000000..37645ed --- /dev/null +++ b/plugins/claims/claims_plugin.py @@ -0,0 +1,239 @@ +import re +from base_plugin import SimpleCommandPlugin +from plugins.core.player_manager import UserLevels, permissions +from utility_functions import extract_name + + +class ClaimsPlugin(SimpleCommandPlugin): + """ +Allows planets to be either protector or unprotected. On protected planets, +only admins can build. Planets are unprotected by default. +""" + name = "claims" + description = "Claims planets." + commands = ["claim", "unclaim", "claim_list", "unclaimable"] + depends = ["player_manager", "command_dispatcher", "planet_protect"] + + def __init__(self): + super(ClaimsPlugin, self).__init__() + + def activate(self): + super(ClaimsPlugin, self).activate() + + #self.protected_planets = self.config.plugin_config.get("protected_planets", []) + #self.player_planets = self.config.plugin_config.get("player_planets", {}) + try: + self.max_claims = self.config.plugin_config['max_claims'] + except KeyError: + self.max_claims = 5 + self.unclaimable_planets = self.config.plugin_config.get("unclaimable_planets", []) + self.protected_planets = self.config.config['plugin_config']['planet_protect']['protected_planets'] + self.player_planets = self.config.config['plugin_config']['planet_protect']['player_planets'] + self.player_manager = self.plugins["player_manager"].player_manager + self.regexes = self.plugins['player_manager'].regexes + + @permissions(UserLevels.ADMIN) + def unclaimable(self, data): + """Set the current planet as unclaimable.\nSyntax: /unclaimable""" + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + if on_ship: + self.protocol.send_chat_message("Can't claim ships (at the moment)") + return + if planet not in self.unclaimable_planets: + self.unclaimable_planets.append(planet) + self.protocol.send_chat_message("Planet successfully set as unclaimable.") + self.logger.info("Planet %s set as unclaimable", planet) + else: + self.unclaimable_planets.remove(planet) + self.protocol.send_chat_message("Planet successfully removed from unclaimable list.") + self.logger.info("Planet %s removed as unclaimable", planet) + self.save() + + @permissions(UserLevels.GUEST) + def claim(self, data): + """Claims the current planet. Only administrators and allowed players can build on claimed planets.\nSyntax: /claim [player]""" + if self.protocol.player.planet in self.unclaimable_planets: + self.protocol.send_chat_message("This planet ^red;cannot^green; be claimed!") + return + try: + my_storage = self.protocol.player.storage + except AttributeError: + return + # set storage to 0 if player never used any of the claim commands + if not 'claims' in my_storage: + my_storage['claims'] = 0 + self.protocol.player.storage = my_storage + # check if max claim limit has been reached + if int(my_storage['claims']) >= self.max_claims: + my_storage['claims'] = self.max_claims + self.protocol.player.storage = my_storage + self.protocol.send_chat_message( + "You already have max (^red;%s^green;) claimed planets!" % str(self.max_claims)) + # assuming player is eligible to claim + elif 0 <= int(my_storage['claims']) <= self.max_claims: + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + if len(data) == 0: + addplayer = self.protocol.player.org_name + first_name_color = self.protocol.player.colored_name(self.config.colors) + else: + addplayer = data[0] + try: + addplayer, rest = extract_name(data) + addplayer = self.player_manager.get_by_name(addplayer).org_name + first_name_color = self.player_manager.get_by_org_name(addplayer).colored_name(self.config.colors) + except: + self.protocol.send_chat_message("There's no player named: ^yellow;%s" % str(addplayer)) + return + + first_name = str(addplayer) + orgplayer = self.protocol.player.org_name + + try: + count = 1 + for name in self.player_planets[planet]: + if name != str(orgplayer) and count == 1: + self.protocol.send_chat_message("You can only claim free planets!") + return + count += 1 + except: + if first_name != orgplayer: + self.protocol.send_chat_message("Use only /claim if you wish to claim a planet!") + return + + try: + for planet in self.player_planets: + if first_name in self.player_planets[self.protocol.player.planet]: + self.protocol.send_chat_message( + "Player ^yellow;%s^green; is already in planet protect list." % first_name_color) + return + except: + planet = self.protocol.player.planet # reset planet back to current planet + + planet = self.protocol.player.planet # reset planet back to current planet + if on_ship and not ("force" in " ".join(data).lower()): + self.protocol.send_chat_message("Can't claim ships (at the moment)") + return + if planet not in self.protected_planets: + self.protected_planets.append(planet) + self.protocol.send_chat_message("Planet successfully claimed.") + self.logger.info("Protected planet %s", planet) + my_storage['claims'] = int(my_storage['claims']) + 1 + self.protocol.player.storage = my_storage + if len(first_name) > 0: + if planet not in self.player_planets: + self.player_planets[planet] = [first_name] + else: + self.player_planets[planet] = self.player_planets[planet] + [first_name] + self.protocol.send_chat_message("Adding ^yellow;%s^green; to planet list" % first_name_color) + else: + if len(first_name) == 0: + self.protocol.send_chat_message("Planet is already claimed!") + else: + if planet not in self.player_planets: + self.player_planets[planet] = [first_name] + else: + self.player_planets[planet] = self.player_planets[planet] + [first_name] + self.protocol.send_chat_message("Adding ^yellow;%s^green; to planet list" % first_name_color) + + self.save() + + @permissions(UserLevels.GUEST) + def claim_list(self, data): + """Displays players registered to the protected planet.\nSyntax: /claim_list""" + try: + my_storage = self.protocol.player.storage + except AttributeError: + return + + if not 'claims' in my_storage: + my_storage['claims'] = 0 + self.protocol.player.storage = my_storage + + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + if on_ship: + self.protocol.send_chat_message("Can't claim ships (at the moment)") + return + if planet in self.player_planets: + self.protocol.send_chat_message("Claimed ^cyan;%s^green; of max ^red;%s^green; claimed planets." % ( + str(my_storage['claims']), str(self.max_claims))) + self.protocol.send_chat_message("Players registered to this planet: ^yellow;" + '^green;, ^yellow;'.join( + self.player_planets[planet]).replace('[', '').replace(']', '')) # .replace("'", '') + elif planet in self.unclaimable_planets: + self.protocol.send_chat_message("Claimed ^cyan;%s^green; of max ^red;%s^green; claimed planets." % ( + str(my_storage['claims']), str(self.max_claims))) + self.protocol.send_chat_message("This planet ^red;cannot^green; be claimed!") + else: + self.protocol.send_chat_message("Claimed ^cyan;%s^green; of max ^red;%s^green; claimed planets." % ( + str(my_storage['claims']), str(self.max_claims))) + self.protocol.send_chat_message("Planet has not been claimed!") + + @permissions(UserLevels.GUEST) + def unclaim(self, data): + """Removes claimed planet, or removes a registered player.\nSyntax: /unclaim [player]""" + try: + my_storage = self.protocol.player.storage + except AttributeError: + return + if not 'claims' in my_storage or int(my_storage['claims']) <= 0: + my_storage['claims'] = 0 + self.protocol.player.storage = my_storage + self.protocol.send_chat_message("You have no claimed planets!") + else: + planet = self.protocol.player.planet + on_ship = self.protocol.player.on_ship + #print(self.player_planets[planet].first()) + #player_name = self.protocol.player.name + if len(data) == 0: + addplayer = self.protocol.player.org_name + first_name_color = self.protocol.player.colored_name(self.config.colors) + else: + addplayer, rest = extract_name(data) + first_name_color = addplayer + + first_name = str(addplayer) + orgplayer = self.protocol.player.org_name + + if on_ship: + self.protocol.send_chat_message("Can't claim ships (at the moment)") + return + try: + count = 1 + for name in self.player_planets[planet]: + #print(first_name, str(name)) + if name != str(orgplayer) and count == 1: + self.protocol.send_chat_message("You can only unclaim planets you've claimed!") + return + if len(data) != 0 and first_name == str(orgplayer): + self.protocol.send_chat_message("Use only /unclaim if you wish to remove protection!") + return + count += 1 + except: + pass + if len(data) == 0: + if planet in self.protected_planets: + del self.player_planets[planet] + self.protected_planets.remove(planet) + self.protocol.send_chat_message("Planet successfully unclaimed.") + self.logger.info("Unprotected planet %s", planet) + my_storage['claims'] = int(my_storage['claims']) - 1 + self.protocol.player.storage = my_storage + else: + self.protocol.send_chat_message("Planet has not been claimed!") + else: + if first_name in self.player_planets[planet]: + self.player_planets[planet].remove(first_name) + self.protocol.send_chat_message("Removed ^yellow;" + first_name_color + "^green; from planet list") + else: + self.protocol.send_chat_message( + "Cannot remove ^yellow;" + first_name_color + "^green; from planet list (not in list)") + self.save() + + def save(self): + self.config.config['plugin_config']['planet_protect']['protected_planets'] = self.protected_planets + self.config.config['plugin_config']['planet_protect']['player_planets'] = self.player_planets + self.config.plugin_config['max_claims'] = self.max_claims + self.config.plugin_config['unclaimable_planets'] = self.unclaimable_planets + self.config.save() # save config file diff --git a/plugins/web_gui/__init__.py b/plugins/web_gui/__init__.py new file mode 100644 index 0000000..c662274 --- /dev/null +++ b/plugins/web_gui/__init__.py @@ -0,0 +1 @@ +from .web_gui_plugin import WebGuiPlugin \ No newline at end of file diff --git a/plugins/web_gui/static/adminstop.html b/plugins/web_gui/static/adminstop.html new file mode 100644 index 0000000..c3f6fc7 --- /dev/null +++ b/plugins/web_gui/static/adminstop.html @@ -0,0 +1,37 @@ + + + + + StarryPy + + + + + + + + + + + + +
+
+
+
+
+ {% if handler.error_message == "" %} +

Server is being stopped!

+ {% else %} +

{{ handler.error_message }}

+ {% end %} +
+
+
+
+
+ + \ No newline at end of file diff --git a/plugins/web_gui/static/ajax/dashboard.html b/plugins/web_gui/static/ajax/dashboard.html new file mode 100644 index 0000000..0c3210a --- /dev/null +++ b/plugins/web_gui/static/ajax/dashboard.html @@ -0,0 +1,92 @@ + +
+
+
+
+
+
+ + Chat +
+ +
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+ + Online Players +
+ +
+
+
+
+
+ +
+
+
+ + Administration +
+ +
+
+
+
+
+
+
+
+
diff --git a/plugins/web_gui/static/ajax/playeredit.html b/plugins/web_gui/static/ajax/playeredit.html new file mode 100644 index 0000000..b0a8115 --- /dev/null +++ b/plugins/web_gui/static/ajax/playeredit.html @@ -0,0 +1,93 @@ +
+ +
+
+
+ {% set iconcolour = "#54ae86" if handler.edit_player.logged_in else "#D15E5E" %} +

Edit {{ handler.edit_player.name }}

+ {% if handler.edit_player.logged_in %} + + {% end %} + {% if handler.player_manager.check_bans(handler.edit_player.ip) %} + + {% else %} + + {% end %} + +
+
+ +
+ {% if handler.error_message != "" %} + {{ handler.error_message }} + {% end %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Original Name{{ handler.edit_player.org_name }}
UUID{{ handler.edit_player.uuid }}
Access Level + +
IP{{ handler.edit_player.ip }}
Last Seen{{ str(handler.edit_player.last_seen).rpartition('.')[0] }}
planet{{ handler.edit_player.planet }}
On Ship{{ handler.edit_player.on_ship }}
+ {% raw xsrf_form_html() %} + +
+ +
+
+
+
+
diff --git a/plugins/web_gui/static/ajax/playerlist.html b/plugins/web_gui/static/ajax/playerlist.html new file mode 100644 index 0000000..83c249d --- /dev/null +++ b/plugins/web_gui/static/ajax/playerlist.html @@ -0,0 +1,37 @@ + + +
+ +
+
+
+ + + + + + + + + + + {% for player in handler.playerlist %} + + {% set iconcolour = "#54ae86" if player.logged_in else "#D15E5E" %} + + + + + + {% end %} + +
NamePlanetAccess LevelLast Seen
{{ player.name }} {% if handler.player_manager.check_bans(player.ip) %} {% end %}{{ player.planet }}{{ player.access_level }}{{ str(player.last_seen).rpartition('.')[0] }}
+
+
+ diff --git a/plugins/web_gui/static/ajax/playerlistonline.html b/plugins/web_gui/static/ajax/playerlistonline.html new file mode 100644 index 0000000..c735003 --- /dev/null +++ b/plugins/web_gui/static/ajax/playerlistonline.html @@ -0,0 +1,36 @@ + + + +
+
+ + + + + + + + + + + {% for player in handler.playerlistonline %} + + + + + + + {% end %} + +
NamePlanetAccess LevelLast Seen
{{ player.name }}{{ player.planet }}{{ player.access_level }}{{ str(player.last_seen).rpartition('.')[0] }}
+
+
+ diff --git a/plugins/web_gui/static/ajax/playerquickmenu.html b/plugins/web_gui/static/ajax/playerquickmenu.html new file mode 100644 index 0000000..0deec43 --- /dev/null +++ b/plugins/web_gui/static/ajax/playerquickmenu.html @@ -0,0 +1,10 @@ +{% if handler.edit_player.logged_in %} + +{% end %} + +{% if handler.player_manager.check_bans(handler.edit_player.ip) %} + +{% else %} + +{% end %} + \ No newline at end of file diff --git a/plugins/web_gui/static/ajax/playersonline.html b/plugins/web_gui/static/ajax/playersonline.html new file mode 100644 index 0000000..9549b9b --- /dev/null +++ b/plugins/web_gui/static/ajax/playersonline.html @@ -0,0 +1,3 @@ + {% for player in handler.playerlistonline %} + {{ player.name }}
+ {% end %} \ No newline at end of file diff --git a/plugins/web_gui/static/css/bootstrap-sortable.css b/plugins/web_gui/static/css/bootstrap-sortable.css new file mode 100644 index 0000000..8924f61 --- /dev/null +++ b/plugins/web_gui/static/css/bootstrap-sortable.css @@ -0,0 +1,84 @@ +table.sortable span.sign { + display: block; + position: absolute; + top: 50%; + right: 5px; + font-size: 12px; + margin-top: -10px; + color: #bfbfc1; +} + +table.sortable span.arrow, span.reversed { + border-style: solid; + border-width: 5px; + font-size: 0; + border-color: #ccc transparent transparent transparent; + line-height: 0; + height: 0; + width: 0; + margin-top: -2px; +} + + table.sortable span.arrow.up { + border-color: transparent transparent #ccc transparent; + margin-top: -7px; + } + +table.sortable span.reversed { + border-color: transparent transparent #ccc transparent; + margin-top: -7px; +} + + table.sortable span.reversed.up { + border-color: #ccc transparent transparent transparent; + margin-top: -2px; + } + + + +table.sortable span.az:before { + content: "a .. z"; +} + +table.sortable span.az.up:before { + content: "z .. a"; +} + +table.sortable span.AZ:before { + content: "A .. Z"; +} + +table.sortable span.AZ.up:before { + content: "Z .. A"; +} + +table.sortable span._19:before { + content: "1 .. 9"; +} + +table.sortable span._19.up:before { + content: "9 .. 1"; +} + +table.sortable span.month:before { + content: "jan .. dec"; +} + +table.sortable span.month.up:before { + content: "dec .. jan"; +} + +table.sortable thead th:not([data-defaultsort=disabled]) { + cursor: pointer; + position: relative; + top: 0; + left: 0; +} + +table.sortable thead th:hover:not([data-defaultsort=disabled]) { + background: #efefef; +} + +table.sortable thead th div.mozilla { + position: relative; +} diff --git a/plugins/web_gui/static/css/footer.css b/plugins/web_gui/static/css/footer.css new file mode 100644 index 0000000..7ce6adb --- /dev/null +++ b/plugins/web_gui/static/css/footer.css @@ -0,0 +1,6 @@ +#footer { + position: fixed; + bottom: 0; + padding-left: 10 px; + padding-bottom: 5px; +} \ No newline at end of file diff --git a/plugins/web_gui/static/css/style.min.css b/plugins/web_gui/static/css/style.min.css new file mode 100644 index 0000000..eddc069 --- /dev/null +++ b/plugins/web_gui/static/css/style.min.css @@ -0,0 +1 @@ +body{color:#525252;background:#6aa6d6 url(../img/devoops_pattern_b10.png) 0 0 repeat}.body-expanded,.modal-open{overflow-y:hidden;margin-right:15px}.body-expanded .expanded-panel,.fancybox-margin .expanded-panel,.modal-open .expanded-panel{margin-right:15px}.body-screensaver{overflow:hidden}h1,.h1,h2,.h2,h3,.h3{margin:0}#logo{position:relative;background:#525252 url(../img/devoops_pattern_b10.png) 0 0 repeat}#logo a{color:#fff;font-family:'Righteous',cursive;display:block;font-size:20px;line-height:50px;background:url(../img/logo.png) right 42px no-repeat;-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;transition:.5s}#logo a:hover{background-position:right 25px;text-decoration:none}.navbar{margin:0;border:0;position:fixed;top:0;left:0;width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;box-shadow:0 1px 2px #272727;z-index:2000}.body-expanded .navbar{z-index:9}a.show-sidebar{float:left;color:#6d6d6d;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}a.show-sidebar:hover{color:#000}#sidebar-left{position:relative;z-index:inherit;padding-bottom:3000px !important;margin-bottom:-3000px !important;background:#6aa6d6 url(../img/devoops_pattern_b10.png) 0 0 repeat;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}#content{position:relative;z-index:10;background:#ebebeb;box-shadow:0 0 6px #131313;padding-bottom:3000px !important;margin-bottom:-2980px !important;overflow:hidden;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.full-content{overflow:hidden;padding:0;margin:0}.nav.main-menu,.nav.msg-menu{margin:0 -15px}.nav.main-menu>li>a,.nav.msg-menu>li>a{text-align:center;color:#f0f0f0;min-height:40px;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background:rgba(0,0,0,0.1)}.nav.main-menu>li>a:hover,.nav.main-menu>li>a:focus,.nav.main-menu>li.active>a,.nav.main-menu .open>a,.nav.main-menu .open>a:hover,.nav.main-menu .open>a:focus,.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover,.dropdown-menu>li.active>a,.nav.msg-menu>li>a:hover,.nav.msg-menu>li>a:focus,.nav.msg-menu>li.active>a,.nav.msg-menu .open>a,.nav.msg-menu .open>a:hover,.nav.msg-menu .open>a:focus{background:rgba(0,0,0,0.1);color:#f0f0f0}.nav.main-menu a.active,.nav.msg-menu a.active{background:rgba(0,0,0,0.2)}.nav.main-menu a.active:hover,.nav.msg-menu a.active:hover{background:rgba(0,0,0,0.2)}.nav.main-menu a.active-parent,.nav.msg-menu a.active-parent{background:rgba(0,0,0,0.3)}.nav.main-menu a.active-parent:hover,.nav.msg-menu a.active-parent:hover{background:rgba(0,0,0,0.3)}.nav.main-menu>li>a>i,.nav.msg-menu>li>a>i{font-size:18px;width:auto;display:block;text-align:center;vertical-align:middle}.main-menu .dropdown-menu{position:absolute;z-index:2001;left:100%;top:0;float:none;margin:0;border:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;padding:0;background:#6aa6d6 url(../img/devoops_pattern_b10.png) 0 0 repeat;box-shadow:none;visibility:hidden}.main-menu .active-parent:hover+.dropdown-menu{visibility:visible}.main-menu .active-parent+.dropdown-menu:hover{visibility:visible}.main-menu .dropdown-menu>li>a{padding:9px 15px 9px 40px;color:#f0f0f0}.main-menu .dropdown-menu>li:first-child>a{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0}.main-menu .dropdown-menu>li:last-child>a{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0}#top-panel{line-height:50px;height:50px;background:#ebebeb}#main{margin-top:50px;min-height:800px;overflow:hidden}#search{position:relative;margin-left:20px}#search>input{width:80%;background:#dfdfdf;border:1px solid #c7c7c7;text-shadow:0 1px 1px #EEE;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;color:#686868;line-height:1em;height:30px;padding:0 35px 0 10px;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}#search>input+i{opacity:0;position:absolute;top:18px;right:10px;color:#fff;-webkit-transition:.4s;-moz-transition:.4s;-o-transition:.4s;transition:.4s}#search>input:focus{width:100%;outline:0}#search>input:focus+i{opacity:1}.panel-menu{margin:0}.top-panel-right{padding-left:0}.panel-menu>li>a{padding:0 5px 0 10px;line-height:50px}.panel-menu>li>a:hover{background:0}.panel-menu a.account{height:50px;padding:5px 0 5px 10px;line-height:18px}.panel-menu i{margin-top:8px;padding:5px;font-size:20px;color:#7bc5d3;line-height:1em;vertical-align:top;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.panel-menu>li>a:hover>i{background:#f5f5f5}.panel-menu i.pull-right{color:#000;border:0;box-shadow:none;font-size:16px;background:none !important}.panel-menu .badge{margin-top:3px;padding:3px 6px;vertical-align:top;background:#cea9a9}.avatar{width:40px;float:left;margin-right:5px}.avatar>img{width:40px;height:40px;border:1px solid #f8f8f8}.user-mini>span{display:block;font-size:12px;color:#363636;margin-bottom:-4px}.user-mini>span.welcome{font-weight:bold;margin-top:2px}.panel-menu .dropdown-menu{position:absolute !important;background:rgba(0,0,0,0.7) !important;padding:0;border:0;right:0;left:auto;min-width:100%}.panel-menu .dropdown-menu>li>a{padding:5px 10px !important;color:#f0f0f0}.panel-menu .dropdown-menu>li>a>i{border:0;padding:0;margin:0;font-size:14px;width:20px;display:inline-block;text-align:center;vertical-align:middle}.well{padding:15px}.box{display:block;z-index:1999;position:relative;border:1px solid #f8f8f8;box-shadow:0 0 4px #d8d8d8;background:transparent;margin-bottom:20px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.full-content .box{border:0;margin-bottom:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.box-header{-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;color:#363636;font-size:16px;position:relative;overflow:hidden;background:#f5f5f5;border-bottom:1px solid #e4e4e4;height:28px}.box-name,.modal-header-name{padding-left:15px;line-height:28px}.box-name:hover{cursor:move}.box-name>i{margin-right:5px}.box-icons{position:absolute;top:0;right:0;z-index:9}.no-move{display:none}.expanded .no-move{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;display:block}.box-content{position:relative;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;padding:15px;background:#fcfcfc}.box-content.dropbox,.box-content.sortablebox{overflow:hidden}.full-content .box-content{height:100%;position:absolute;width:100%;left:0;top:0}.box-icons a{cursor:pointer;text-decoration:none !important;border-left:1px solid #fafafa;height:26px;line-height:26px;width:28px;display:block;float:left;text-align:center;color:#b8b8b8 !important;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.box-icons a.beauty-table-to-json{width:auto;padding:0 10px;font-size:14px}.box-icons a:hover{box-shadow:inset 0 0 1px 0 #cecece}.expanded a.close-link{display:none}#sidebar-left.col-xs-2{opacity:0;width:0;padding:0}.sidebar-show #sidebar-left.col-xs-2{opacity:1;width:16.666666666666664%;padding:0 15px}.sidebar-show #content.col-xs-12{opacity:1;width:83.33333333333334%}.expanded{overflow-y:scroll;border:0;z-index:3000 !important;position:fixed;width:100%;height:100%;top:0;left:0;padding:0;background:rgba(0,0,0,0.2);-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.expanded-padding{background:rgba(0,0,0,0.7);padding:50px;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.no-padding{padding:0 !important}.padding-15{padding:15px !important}.no-padding .table-bordered{border:0;margin:0}.no-padding .table-bordered thead tr th:first-child,.no-padding .table-bordered tbody tr th:first-child,.no-padding .table-bordered tfoot tr th:first-child,.no-padding .table-bordered thead tr td:first-child,.no-padding .table-bordered tbody tr td:first-child,.no-padding .table-bordered tfoot tr td:first-child{border-left:0 !important}.no-padding .table-bordered thead tr th:last-child,.no-padding .table-bordered tbody tr th:last-child,.no-padding .table-bordered tfoot tr th:last-child,.no-padding .table-bordered thead tr td:last-child,.no-padding .table-bordered tbody tr td:last-child,.no-padding .table-bordered tfoot tr td:last-child{border-right:0 !important}.table-heading thead tr{background-color:#f0f0f0;background-image:-webkit-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-moz-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-ms-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-o-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:linear-gradient(to bottom,#f0f0f0,#dfdfdf)}table.no-border-bottom tr:last-child td{border-bottom:0}.dataTables_wrapper{overflow:hidden}.dataTables_wrapper table.table{clear:both;max-width:inherit;margin-bottom:0}.table-datatable *,.table-datatable :after,.table-datatable :before{margin:0;padding:0;-webkit-box-sizing:content-box;box-sizing:content-box;-moz-box-sizing:content-box}.table-datatable label{position:relative;display:block;font-weight:400}.table-datatable tbody td{vertical-align:middle !important}.table-datatable img{margin-right:10px;border:1px solid #f8f8f8;width:40px}.table-datatable .sorting{background:url(../img/sort.png) right center no-repeat;padding-right:16px;cursor:pointer}.table-datatable .sorting_asc{background:url(../img/sort-asc.png) right center no-repeat;padding-right:16px;cursor:pointer}.table-datatable .sorting_desc{background:url(../img/sort-desc.png) right center no-repeat;padding-right:16px;cursor:pointer}div.DTTT_collection_background{z-index:2002}div.DTTT .btn{color:#333 !important;font-size:12px}ul.DTTT_dropdown.dropdown-menu{z-index:2003;background:rgba(0,0,0,0.7) !important;padding:0;border:0;margin:0;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;min-width:157px}ul.DTTT_dropdown.dropdown-menu li{position:relative}ul.DTTT_dropdown.dropdown-menu>li>a{position:relative;display:block;padding:5px 10px !important;color:#f0f0f0 !important}ul.DTTT_dropdown.dropdown-menu>li:first-child>a{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}ul.DTTT_dropdown.dropdown-menu>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}ul.DTTT_dropdown.dropdown-menu>li:hover>a{background:rgba(0,0,0,0.3);color:#f0f0f0}.dataTables_wrapper input[type="text"]{display:block;width:90%;height:26px;padding:2px 12px;font-size:14px;line-height:1.428571429;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-appearance:none;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.dataTables_wrapper input[type="text"]:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}#breadcrumb{padding:0;line-height:40px;background:#525252;background:#5a8db6 url(../img/devoops_pattern_b10.png) 0 0 repeat;margin-bottom:20px}.breadcrumb{padding:0 15px;background:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;margin:0}.breadcrumb>li>a{color:#d8d8d8}.breadcrumb>li>a:hover,.breadcrumb>li:last-child>a{color:#f8f8f8}.bs-callout{padding:15px;border-left:3px solid #525252;background:#dfdfdf}.bs-callout h4{margin-top:0;margin-bottom:5px;color:#525252}.no-padding .bs-callout{border:0}.page-header{margin:0 0 10px;border-bottom:1px solid #c7c7c7}.box-content .page-header,legend,.full-calendar .page-header{margin:0 0 10px;border-bottom:1px dashed #b6b6b6}.invoice-header{margin:0 0 10px;border-bottom:1px dashed #b6b6b6;display:inline-block}.box-content .form-group,.devoops-modal-inner .form-group{margin-top:15px;margin-bottom:15px}.show-grid [class^="col-"]{padding-top:10px;padding-bottom:10px;background-color:#525252;background-color:rgba(129,199,199,0.2);border:1px solid #ebebeb}.show-grid [class^="col-"]:hover{padding-top:10px;padding-bottom:10px;background-color:rgba(107,134,182,0.2);border:1px solid #ebebeb}.show-grid,.show-grid-forms{margin-bottom:15px}.show-grid-forms [class^="col-"]{padding-top:10px;padding-bottom:10px}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th,td.beauty-hover{background-color:rgba(219,219,219,0.3) !important}.table-hover>tbody>tr:hover>td.beauty-hover:hover{background-color:rgba(219,219,219,0.9) !important}.DTTT.btn-group{position:absolute;top:-28px;right:83px;border-right:1px solid #dbdbdb}.DTTT.btn-group a{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;line-height:1em;font-size:14px;font-weight:bold;outline:0;box-shadow:none !important;padding:6px 12px;margin:0;background:#f7f7f7;border:0}#screensaver{position:fixed;top:0;left:0;width:100%;height:100%;z-index:3000;background:#000;display:none}#screensaver.show{display:block}#canvas{position:relative}#screensaver i{position:absolute;top:50px;right:50px;background:rgba(255,255,255,0.5);line-height:100px;width:100px;height:100px;text-align:center;font-size:60px;color:rgba(0,0,0,0.8);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well pre{padding:0;margin-top:0;margin-bottom:0;background-color:transparent;border:0;white-space:nowrap}.well pre code{white-space:normal}.btn{border-width:1px;border-style:solid;border-width:1px;text-decoration:none;border-color:rgba(0,0,0,0.3);cursor:pointer;outline:0;font-family:"Lucida Grande","Lucida Sans","Lucida Sans Unicode","Segoe UI",Verdana,sans-serif;display:inline-block;vertical-align:top;position:relative;font-size:12px;font-weight:bold;text-align:center;background-color:#a2a2a2;background:#a2a2a2 -moz-linear-gradient(top,rgba(255,255,255,0.6),rgba(255,255,255,0));background:#a2a2a2 -webkit-gradient(linear,0 0,0 100%,from(rgba(255,255,255,0.6)),to(rgba(255,255,255,0)));line-height:24px;margin:0 0 10px 0;padding:0 10px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-moz-user-select:none;-webkit-user-select:none;outline:none !important}.btn-label-left,.btn-label-right{padding:0 10px}.btn-label-left span{position:relative;left:-10px;display:inline-block;padding:0 8px;background:rgba(0,0,0,0.1)}.btn-label-right span{position:relative;right:-10px;display:inline-block;padding:0 8px;background:rgba(0,0,0,0.1)}.btn i{vertical-align:middle}.btn-app{width:80px;height:80px;padding:0;font-size:16px}.btn-app i{font-size:36px;line-height:78px;display:block}.btn-app-sm{width:50px;height:50px;padding:0;font-size:12px}.btn-app-sm i{font-size:18px;line-height:48px;display:block}.btn-circle{-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;border:2px solid rgba(0,0,0,0.25)}.btn.active{background-image:none;outline:0;-webkit-box-shadow:none;box-shadow:none}.btn-default,.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active,.progress-bar{background-color:#d8d8d8;border-color:rgba(0,0,0,0.3);color:#929292}.btn-primary,.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active,.table>thead>tr>td.primary,.table>tbody>tr>td.primary,.table>tfoot>tr>td.primary,.table>thead>tr>th.primary,.table>tbody>tr>th.primary,.table>tfoot>tr>th.primary,.table>thead>tr.primary>td,.table>tbody>tr.primary>td,.table>tfoot>tr.primary>td,.table>thead>tr.primary>th,.table>tbody>tr.primary>th,.table>tfoot>tr.primary>th{background-color:#6aa6d6;border-color:rgba(0,0,0,0.3);color:#f8f8f8}.btn-success,.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active,.progress-bar-success,.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#63cc9e;border-color:rgba(0,0,0,0.3);color:#f8f8f8}.btn-info,.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active,.progress-bar-info,.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#7bc5d3;border-color:rgba(0,0,0,0.3);color:#f8f8f8}.btn-warning,.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active,.progress-bar-warning,.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#dfd271;border-color:rgba(0,0,0,0.3);color:#f8f8f8}.btn-danger,.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active,.progress-bar-danger,.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#d15e5e;border-color:rgba(0,0,0,0.3);color:#f8f8f8}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#525252;background-color:#b8b8b8;border-color:rgba(0,0,0,0.3)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary,.table-hover>tbody>tr>td.primary:hover,.table-hover>tbody>tr>th.primary:hover,.table-hover>tbody>tr.primary:hover>td,.table-hover>tbody>tr.primary:hover>th{color:#fff;background-color:#5a8db6;border-color:rgba(0,0,0,0.3)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{color:#fff;background-color:#54ae86;border-color:rgba(0,0,0,0.3)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{color:#fff;background-color:#69a8b4;border-color:rgba(0,0,0,0.3)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{color:#fff;background-color:#beb360;border-color:rgba(0,0,0,0.3)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{color:#fff;background-color:#b25050;border-color:rgba(0,0,0,0.3)}.progress{overflow:visible}.progress-ui{height:10px}.progress-bar{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.progress-bar.ui-widget-content{background:0;border:0;height:100%;position:relative}.progress-bar .ui-state-default{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;height:10px;width:10px;top:0;margin-left:-5px;cursor:pointer;border:0 solid #d3d3d3;outline:none !important;background-color:#f0f0f0;background-image:-webkit-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-moz-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-ms-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-o-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:linear-gradient(to bottom,#f0f0f0,#dfdfdf)}.progress-bar .ui-widget-header{background:#d8d8d8}.progress-bar-primary .ui-widget-header{background:#6aa6d6;color:#f8f8f8}.progress-bar-success .ui-widget-header{background:#63cc9e;color:#f8f8f8}.progress-bar-info .ui-widget-header{background:#7bc5d3;color:#f8f8f8}.progress-bar-warning .ui-widget-header{background:#dfd271;color:#f8f8f8}.progress-bar-danger .ui-widget-header{background:#d15e5e;color:#f8f8f8}.progress-bar .ui-state-default{background:#b8b8b8}.progress-bar-primary .ui-state-default{background:#5a8db6}.progress-bar-success .ui-state-default{background:#54ae86}.progress-bar-info .ui-state-default{background:#69a8b4}.progress-bar-warning .ui-state-default{background:#beb360}.progress-bar-danger .ui-state-default{background:#b25050}.slider-range-min-amount,.slider-range-max-amount,.slider-range-amount{border:0;background:0;outline:none !important}.progress-bar.ui-slider-vertical{width:20px}.progress-bar.ui-slider-vertical .ui-state-default{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;height:20px;width:20px;top:auto;margin-left:0;left:0}#equalizer .progress{height:160px;display:inline-block;margin:15px}.beauty-table{width:100%;border-collapse:separate;border-spacing:0}.beauty-table input{border:1px solid transparent;background:0;font-size:16px;text-align:center;padding:2px 15px !important;width:100%;outline:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.beauty-table input:focus{border:1px solid #dfdfdf;background:#fefefe;font-size:16px;text-align:center;padding:2px 15px !important;width:100%;outline:0}.c{color:#999;display:block}.nt{color:#2f6f9f}.na{color:#4f9fcf}.s{color:#d44950}.radio,.checkbox,.radio-inline,.checkbox-inline{position:relative}.radio label,.checkbox label,.radio-inline label,.checkbox-inline label{font-weight:normal;cursor:pointer;padding-left:8px;-webkit-transition:1s;-moz-transition:1s;-o-transition:1s;transition:1s}.radio+.radio,.checkbox+.checkbox{margin-top:10px}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;clip:rect(0,0,0,0)}.checkbox i,.checkbox-inline i,.radio i,.radio-inline i{cursor:pointer;position:absolute;left:0;top:0;font-size:24px;-webkit-transition:1s;-moz-transition:1s;-o-transition:1s;transition:1s}.checkbox i.small,.checkbox-inline i.small,.radio i.small,.radio-inline i.small{font-size:18px;top:2px}.checkbox input[type=checkbox]:checked+i:before,.checkbox-inline input[type=checkbox]:checked+i:before{content:"\f046"}.radio input[type=radio]:checked+i:before,.radio-inline input[type=radio]:checked+i:before{content:"\f192"}.toggle-switch{position:relative;width:60px}.toggle-switch input{display:none}.toggle-switch label{display:block;overflow:hidden;cursor:pointer;-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px}.toggle-switch-inner{width:200%;margin-left:-100%;-webkit-transition:margin .3s ease-in 0;-moz-transition:margin .3s ease-in 0;-o-transition:margin .3s ease-in 0;transition:margin .3s ease-in 0}.toggle-switch-inner:before,.toggle-switch-inner:after{float:left;width:50%;height:20px;padding:0;line-height:20px;font-size:12px;text-shadow:1px 1px 1px #fff;color:#929292;background-color:#f5f5f5;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.toggle-switch-inner:before{content:"ON";padding-left:15px;-webkit-border-radius:20px 0 0 20px;-moz-border-radius:20px 0 0 20px;border-radius:20px 0 0 20px}.toggle-switch-inner:after{content:"OFF";padding-right:15px;text-align:right;-webkit-border-radius:0 20px 20px 0;-moz-border-radius:0 20px 20px 0;border-radius:0 20px 20px 0}.toggle-switch-switch{width:20px;margin:0;border:2px solid #d8d8d8;-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px;position:absolute;top:0;bottom:0;right:40px;color:#f8f8f8;line-height:1em;text-shadow:0 0 1px #adadad;text-align:center;-webkit-transition:all .3s ease-in 0;-moz-transition:all .3s ease-in 0;-o-transition:all .3s ease-in 0;transition:all .3s ease-in 0;background-color:#f0f0f0;background-image:-webkit-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-moz-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-ms-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:-o-linear-gradient(top,#f0f0f0,#dfdfdf);background-image:linear-gradient(to bottom,#f0f0f0,#dfdfdf)}.toggle-switch input:checked+.toggle-switch-inner{margin-left:0}.toggle-switch input:checked+.toggle-switch-inner+.toggle-switch-switch{right:0}.toggle-switch-danger input:checked+.toggle-switch-inner+.toggle-switch-switch{border:2px solid #d15e5e;background:#d15e5e}.toggle-switch-warning input:checked+.toggle-switch-inner+.toggle-switch-switch{border:2px solid #dfd271;background:#dfd271}.toggle-switch-info input:checked+.toggle-switch-inner+.toggle-switch-switch{border:2px solid #7bc5d3;background:#7bc5d3}.toggle-switch-success input:checked+.toggle-switch-inner+.toggle-switch-switch{border:2px solid #63cc9e;background:#63cc9e}.toggle-switch-primary input:checked+.toggle-switch-inner+.toggle-switch-switch{border:2px solid #6aa6d6;background:#6aa6d6}.select2-container{width:100%}.select2-container .select2-choice{height:30px}.knob-slider{position:relative;text-align:center;display:inline-block;width:100%;margin-bottom:5px}.knob-slider>div{display:inline-block !important}.knob-slider input{outline:none !important}.ipod{background:#dedede;text-align:center;padding:50px 0}.knob-clock{text-align:center}.knob-clock>div{font-size:50px;text-align:center;color:#a2a2a2}.knob{border:0;background:0}.box-pricing:hover{box-shadow:0 0 5px #525252;-webkit-transition:.5s;-moz-transition:.5s;-o-transition:.5s;transition:.5s}.box-pricing .row-fluid>div{padding:18px 15px 8px;line-height:1.428571429;vertical-align:top}.box-pricing .row-fluid.centered>div{background-color:#f5f5f5;padding:8px;text-align:center}.box-pricing .row-fluid.centered>div:nth-child(odd){background-color:#f9f9f9}.box-pricing .box-header{height:80px;padding:10px 0}.box-pricing .box-name{padding:0 10px;text-align:center}.box-pricing .box-name:hover{cursor:inherit}#messages #breadcrumb{margin-bottom:0;position:fixed;width:100%;z-index:2}#messages-menu{position:fixed;top:90px;background:#a5a5a5;margin:0;height:100%;z-index:2}#messages-list{margin-top:40px;padding:0}.one-list-message{background:#f1f1f1;border-bottom:1px solid #CCC;padding:15px 15px 15px 25px;margin:0}.one-list-message .checkbox{margin:0;overflow:hidden;white-space:nowrap}.one-list-message .message-title{overflow:hidden;white-space:nowrap;width:80%}.one-list-message .message-date{overflow:hidden;white-space:nowrap;font-size:11px;line-height:20px;text-align:center;position:absolute;right:10px;font-weight:bold;background:#d8d8d8;padding:0;width:50px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;color:#000}.form-control{height:26px;padding:2px 12px}.input-lg{height:39px}.input-sm{height:18px}.bg-default{background:#d8d8d8 !important}.bg-primary{background:#6aa6d6 !important;color:#f8f8f8 !important}.bg-success{background:#63cc9e !important;color:#f8f8f8 !important}.bg-info{background:#7bc5d3 !important;color:#f8f8f8 !important}.bg-warning{background:#dfd271 !important;color:#f8f8f8 !important}.bg-danger{background:#d15e5e !important;color:#f8f8f8 !important}.txt-default{color:#d8d8d8 !important}.txt-primary{color:#6aa6d6 !important}.txt-success,.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#63cc9e !important}.txt-info{color:#7bc5d3 !important}.txt-warning,.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#dfd271 !important}.txt-danger,.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#d15e5e !important}.has-success .form-control{border-color:#63cc9e}.has-warning .form-control{border-color:#dfd271}.has-error .form-control{border-color:#d15e5e}.has-success .form-control:focus{border-color:#63cc9e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #63cc9e;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #63cc9e}.has-warning .form-control:focus{border-color:#dfd271;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dfd271;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dfd271}.has-error .form-control:focus{border-color:#d15e5e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d15e5e;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d15e5e}.select2-container-multi .select2-choices{min-height:26px;display:block;height:26px;padding:0 0 0 8px;overflow:hidden;position:relative;border:1px solid #aaa;white-space:nowrap;line-height:26px;color:#444;text-decoration:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;background-clip:padding-box;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff;background-image:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(0.5,#fff));background-image:-webkit-linear-gradient(center bottom,#eee 0,#fff 50%);background-image:-moz-linear-gradient(center bottom,#eee 0,#fff 50%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff',endColorstr = '#eeeeee',GradientType = 0);background-image:linear-gradient(top,#fff 0,#eee 50%)}.select2-container-multi .select2-choices .select2-search-field input{padding:0;margin:0}.has-feedback .form-control-feedback{width:26px;height:26px;line-height:26px}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{min-height:inherit;padding-top:0}.form-horizontal .control-label{padding-top:4px}.input-group-addon{padding:0 6px}.form-group .form-control,.form-group .input-group{margin-bottom:5px}.input-group .form-control{margin:0}#ui-datepicker-div{background:rgba(0,0,0,0.7) !important;border:0}#ui-datepicker-div .ui-widget-header{background:rgba(0,0,0,0.2);border:0;border-bottom:1px solid #686868;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;color:#f8f8f8;padding:1px 0}#ui-datepicker-div.ui-widget-content{color:#f8f8f8 !important}#ui-datepicker-div .ui-state-default,#ui-datepicker-div .ui-widget-content .ui-state-default,#ui-datepicker-div .ui-widget-header .ui-state-default{background:0;border:0;color:#f8f8f8;text-align:center}#ui-datepicker-div .ui-state-hover,#ui-datepicker-div.ui-widget-content .ui-state-hover,#ui-datepicker-div .ui-widget-header .ui-state-hover,#ui-datepicker-div .ui-state-focus,#ui-datepicker-div.ui-widget-content .ui-state-focus,#ui-datepicker-div .ui-widget-header .ui-state-focus,#ui-datepicker-div .ui-state-highlight,#ui-datepicker-div.ui-widget-content .ui-state-highlight,#ui-datepicker-div .ui-widget-header .ui-state-highlight{background:rgba(0,0,0,0.3) !important;border:0;top:2px}#ui-datepicker-div .ui-datepicker-group{border-left:1px solid #686868}#ui-datepicker-div .ui-datepicker-group:first-child{border-left:0}#ui-datepicker-div .ui-datepicker-buttonpane{margin:0}#ui-datepicker-div .ui-datepicker-group table{margin:0 auto !important}.ui-datepicker .ui-datepicker-prev{left:2px !important;cursor:pointer}.ui-datepicker .ui-datepicker-next{right:2px !important;cursor:pointer}.ui-icon-circle-triangle-w{background:url(../img/ui-left.png) 0 0 no-repeat !important}.ui-icon-circle-triangle-e{background:url(../img/ui-right.png) 0 0 no-repeat !important}.ui-icon-circle-arrow-s{background:url(../img/ui-accordion-down.png) 0 0 no-repeat !important}.ui-icon-circle-arrow-e{background:url(../img/ui-accordion-right.png) 0 0 no-repeat !important}#ui-datepicker-div .ui-slider-horizontal{background:rgba(0,0,0,0.5);height:4px;border:0}#ui-datepicker-div .ui-slider-horizontal .ui-slider-handle{background:#d8d8d8 !important;border:1px solid #f8f8f8;height:8px;width:8px;top:-2px;margin-left:-4px;outline:0;cursor:pointer}.ui-spinner-input{margin:0}.ui-spinner .form-control{margin-bottom:0}#tabs.ui-widget-content,#tabs .ui-widget-header{border:0;background:0;padding:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}#tabs .ui-widget-header{border-bottom:1px solid #d8d8d8}#tabs .ui-state-default,#tabs.ui-widget-content .ui-state-default,#tabs .ui-widget-header .ui-state-default{border:0;margin:0 0 -1px 0;background:none !important}#tabs .ui-state-active,#tabs.ui-widget-content .ui-state-active,#tabs .ui-widget-header .ui-state-active{background:none !important}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin:0;padding:0}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{padding:5px 15px;outline:none !important}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{background:#fcfcfc;border:1px solid #d8d8d8;border-bottom:0}.ui-tabs .ui-tabs-nav{padding:0}.ui-tabs .ui-tabs-panel{padding:1em 0}.ui-widget{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.jqstooltip{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;border:0 !important;text-align:center !important;margin:0 !important;width:50px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;padding:0}.ui-accordion .ui-accordion-header{padding:6px 12px;margin:0;top:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-accordion .ui-accordion-icons{padding-left:28px}.ui-accordion-header.ui-state-default{background:#f5f5f5 !important;border:1px solid #fcfcfc;border-left:0;border-right:0}.ui-accordion-header.ui-state-hover,.ui-accordion-header.ui-state-focus{background:#ebebeb !important}.ui-accordion-header.ui-state-active{background:#d8d8d8 !important}.ui-accordion .ui-accordion-content{padding:10px 12px;background:0;border:1px solid #d8d8d8;border-top:0;border-bottom:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}#simple_gallery{text-align:center}#simple_gallery a.fancybox{display:inline-block;padding:5px}#simple_gallery a.fancybox img{width:100%;padding:2px;border:1px solid #979797;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}#simple_gallery a.fancybox img:hover{box-shadow:0 0 10px #c7c7c7}.justifiedGallery{overflow:hidden;width:100%}.jg-row{position:relative;white-space:nowrap}.justifiedGallery .jg-image{position:absolute;display:inline-block;vertical-align:top;margin-left:0}.justifiedGallery .jg-image a{text-decoration:none}.justifiedGallery .jg-image img{border:0}.justifiedGallery .jg-image-label{white-space:normal;font:normal 12px arial;background:#000;color:#fff;position:absolute;left:0;right:0;padding:5px 5px 10px 8px;text-align:left;opacity:0}.ex-tooltip{position:absolute;display:none;z-index:2000}.morris-hover{position:absolute;z-index:1000}.morris-hover.morris-default-style,.ex-tooltip{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;padding:6px 20px;color:#525252;background:rgba(255,255,255,0.8);font-size:12px;text-align:center}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:.25em 0}.morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:.1em 0}#dashboard-header{margin-bottom:20px}#dashboard_links{padding:0}#dashboard_links .nav{background:#3575a0 url(../img/devoops_pattern_b10.png) 0 0 repeat;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;overflow:hidden}#dashboard_links .nav-stacked>li{border-bottom:1px solid rgba(0,0,0,0.25);border-top:1px solid rgba(255,255,255,0.12);font-size:12px;font-weight:700;line-height:15px;padding:0;margin:0}#dashboard_links .nav-pills>li>a{color:#f8f8f8;display:block;padding:20px 10px 20px 15px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;outline:0}#dashboard_links .nav-pills>li.active{border-top-color:rgba(0,0,0,0.11);position:relative;margin:0}#dashboard_links .nav-pills>li.active>a,#dashboard_links .nav-pills>li.active>a:hover,#dashboard_links .nav-pills>li.active>a:focus,#dashboard_links .nav>li>a:hover,#dashboard_links .nav>li>a:focus{background:rgba(0,0,0,0.1)}#dashboard_links .nav-pills>li.active>a:before{font-family:FontAwesome;content:"\f0da";position:absolute;left:-2px;font-size:30px;color:#f8f8f8}#dashboard_tabs{background:#f8f8f8;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}#dashboard-overview{padding-bottom:15px}.sparkline-dashboard{float:left;margin-right:10px;text-align:center}.sparkline-dashboard-info{float:left;display:block;text-align:center}.sparkline-dashboard-info span{display:block;font-weight:bold;color:#b25050}#ow-marketplace{margin-top:20px}.ow-server{padding-top:8px;padding-bottom:25px}.ow-server:hover{background:#e7e7e7}.ow-server .page-header{padding-bottom:3px}.ow-server h4 i{position:absolute;left:15px}.ow-server small{position:absolute;right:15px;top:51px}.ow-server-bottom{margin-top:25px}.ow-server-bottom .knob-slider{font-size:11px}#ow-server-footer{overflow:hidden;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.ow-settings{position:absolute;top:7px;left:40px;display:none}.ow-settings a{color:#525252}.ow-server:hover .ow-settings{display:block}#ow-server-footer a{display:block;padding:10px 0;border-left:1px solid #f8f8f8;text-decoration:none}#ow-server-footer a:first-child{border-left:0}#ow-server-footer span{display:block}.m-table>thead>tr>th,.m-table>tbody>tr>th,.m-table>tfoot>tr>th,.m-table>thead>tr>td,.m-table>tbody>tr>td,.m-table>tfoot>tr>td{vertical-align:middle;padding:2px 5px}.m-ticker span{display:block;font-size:.8em;line-height:1em}.m-price{text-align:right}.m-change .fa-angle-up{color:#54ae86;font-weight:bold}.m-change .fa-angle-down{color:#b25050;font-weight:bold}#ow-summary{font-size:12px}#ow-summary b{float:right;padding:1px 4px;margin:1px;border:1px solid #d8d8d8;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}#ow-donut{margin:0 0 20px}#ow-donut>div{padding:0}#ow-activity .row{margin:0 0 0 -15px;font-size:13px}#ow-setting{border:1px solid #c7c7c7;padding:0;position:absolute;width:158px;height:28px;top:1px;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;opacity:0;right:-200px;-webkit-transition:.1s;-moz-transition:.1s;-o-transition:.1s;transition:.1s}#ow-marketplace:hover #ow-setting{opacity:1;right:15px}#ow-setting a{text-align:center;float:left;margin-left:10px;color:#d8d8d8;font-size:16px;display:block;line-height:28px;width:20px;height:26px;-webkit-transition:.1s;-moz-transition:.1s;-o-transition:.1s;transition:.1s}#ow-setting a:hover{font-size:16px;color:#222;line-height:24px}#ow-licenced{margin:20px 0}#ow-licenced .row{margin:0}#ow-stat .row{margin:0}#dashboard-clients .one-list-message{background:0;padding:10px 15px}#dashboard-clients .one-list-message:last-child{border-bottom:0}#dashboard-clients .one-list-message .message-date{position:relative;width:auto;right:auto;left:15px;padding:0 15px}.btn+.dropdown-menu{margin-top:-10px;background:rgba(0,0,0,0.7) !important;padding:0;border:0;right:0;left:auto;min-width:100%}.btn+.dropdown-menu>li>a{padding:5px 10px !important;color:#f0f0f0}.v-txt{-moz-transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-o-transform:rotate(-90deg);position:absolute;top:60px;left:-20px;color:#d8d8d8;font-size:18px;box-shadow:0 0 10px #d8d8d8;padding:0 5px}.full-calendar{padding:25px 0;background:#fcfcfc}.external-event{padding:2px 6px;margin:4px 0;background:#f5f5f5}.external-event:hover{cursor:move;background:#6aa6d6;color:#f8f8f8}#add-new-event{background:#ebebeb;margin-bottom:30px;padding:10px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.modal-backdrop{z-index:2000}.modal{z-index:2001}.fc-event{border:1px solid #6aa6d6;background-color:#6aa6d6}.qq-upload-drop-area{position:absolute;background:#fcfcfc;width:100%;height:100%}.qq-upload-button{float:right;margin:20px 15px 0 0}.qq-upload-list{position:relative;z-index:3;margin:60px 15px 0;padding:0;list-style:none}.qq-upload-list li{position:relative;display:inline-block;padding:15px;margin:15px;border:1px solid #e6e6e6;text-align:center;font-size:12px;background:rgba(245,245,245,0.9)}.qq-upload-settings{opacity:0;visibility:hidden;bottom:0;position:absolute;width:100%;left:0;padding:7px 0;background:#FFF;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s}.qq-upload-list li:hover .qq-upload-settings{opacity:1;visibility:visible}.qq-upload-list li img{border:1px solid #b4b4b4;margin-bottom:5px}.qq-upload-filename{display:block;overflow:hidden}.qq-upload-file,.qq-upload-size,.qq-upload-status-text{display:block}.qq-dropped-zone{position:absolute;top:5%;left:50%;margin-left:-71px;text-align:center;font-weight:bold}.qq-dropped-zone i{font-size:5em;display:block;color:#f5f5f5;text-shadow:0 -1px 1px #d8d8d8}#page-500 h1,.page-404 h1{font-size:5em}.page-404 .form-inline{margin:40px auto;width:60%;padding:15px;background:#fafafa;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.page-404 .input-group-btn:last-child>.btn,.page-404 .input-group-btn:last-child>.btn-group{margin-left:-1px;margin-bottom:0;height:39px}#page-500 h3,.page-404 h3{margin:5px 0 20px}.preloader{position:absolute;width:100%;height:100%;left:0;background:#ebebeb;z-index:2000}.devoops-getdata{position:absolute;top:25px;left:15px;color:#ebebeb}#page-500,#page-login{position:absolute;height:100%;width:100%}#page-500{background:#ebebeb}#page-500 img{display:block;margin:30px auto}#page-login .logo{position:absolute}#page-login h3{font-size:20px;font-family:'Righteous',cursive}#page-login .text-right{margin-top:15px}#page-login .box{margin-top:15%}.one-result{margin-top:20px}.one-result p{margin:0}.large{font-size:1.25em}.nav-search>li.active>a{background:#f0f0f0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;color:#525252;border-bottom:1px solid #cecece;font-weight:bold}.page-feed .avatar{width:60px;float:left;margin:10px 15px;text-align:center;overflow:hidden}.page-feed .avatar img{width:60px;height:60px;border:1px solid #f8f8f8}.page-feed-content{position:relative;padding:3px 15px 5px;background:#fcfcfc;margin-left:90px;min-height:80px}.page-feed-content small.time{font-style:italic}.page-feed .page-feed-content:before{font-family:FontAwesome;content:"\f0d9";position:absolute;left:-10px;top:15px;font-size:30px;color:#fcfcfc}.likebox{overflow:hidden}.likebox .navbar-nav{margin:0}.likebox .navbar-nav li{margin-right:15px;float:left}.likebox .fa-thumbs-up{color:#6aa6d6}.likebox .fa-thumbs-down{color:#d15e5e}#modalbox{display:none;position:fixed;overflow:auto;overflow-x:hidden;top:0;right:0;bottom:0;left:0;z-index:5000;background:rgba(0,0,0,0.8)}#modalbox .devoops-modal{position:absolute;top:90px;margin-left:-300px;left:50%;border:1px solid #f8f8f8;box-shadow:0 0 20px #6aa6d6;background:transparent;margin-bottom:20px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;width:600px;z-index:6000}#modalbox .devoops-modal-header{color:#363636;font-size:16px;position:relative;overflow:hidden;background:#f5f5f5;border-bottom:1px solid #e4e4e4;height:28px}#modalbox .devoops-modal-inner{position:relative;overflow:hidden;padding:15px;background:#fcfcfc}#modalbox .devoops-modal-bottom{position:relative;overflow:hidden;padding:15px;background:#d8d8d8}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:4px 10px;margin-left:-1px;line-height:1.428571429;color:#969696;text-decoration:none;background-color:#f5f5f5;border:1px solid #d8d8d8}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#8a8a8a;background-color:#eee}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#979797;cursor:not-allowed;background-color:#fcfcfc;border-color:#d8d8d8}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#6aa6d6;border-color:#6aa6d6}.fancybox-nav{position:fixed;width:50%}.fancybox-close{position:fixed;top:20px;right:36px;background:url(../img/times.png) 0 0 no-repeat}.fancybox-prev span{left:21px;background:url(../img/chevron-left.png) 0 0 no-repeat}.fancybox-next span{right:36px;background:url(../img/chevron-right.png) 0 0 no-repeat}#social a{margin:10px 3px;color:#666;display:block;float:left}#event_delete{margin-left:20px}@media(min-width:768px){#sidebar-left.col-sm-2{opacity:1;width:16.666666666666664%;padding:0 15px}.sidebar-show #sidebar-left.col-sm-2{opacity:0;width:0;padding:0}.sidebar-show #content.col-sm-10{opacity:1;width:100%}.page-404 .form-inline{width:60%}}@media(min-width:992px){.nav.main-menu>li>a,.nav.msg-menu>li>a{text-align:left}.nav.main-menu>li>a>i,.nav.msg-menu>li>a>i{font-size:14px;width:20px;display:inline-block}.main-menu .dropdown-menu{position:relative;z-index:inherit;left:0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;background:rgba(0,0,0,0.2);visibility:visible}.main-menu .dropdown-menu>li>a{-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important}.page-404 .form-inline{width:40%}}@media(max-width:767px){#main{margin-top:100px}#messages-menu{top:140px}.page-404 .form-inline{width:100%}#dashboard_links .nav{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}#dashboard_links .nav-stacked>li{float:left}#dashboard_links .nav-pills>li>a{padding:15px}#dashboard_links .nav-pills>li.active>a:before{bottom:0;left:50%;margin-left:-9px}}@media(max-width:620px){.user-mini{display:none}}@media(max-width:400px){.panel-menu a.account{padding:5px 0 5px 0}.avatar{margin:0}.panel-menu i.pull-right{margin-left:0}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background:0}#dashboard_links .nav-stacked>li{float:none}#dashboard_links .nav-pills>li.active>a:before{display:none}}#chat {width: 100%;height: 25em;overflow: auto;margin-bottom: 15px} diff --git a/plugins/web_gui/static/fonts/glyphicons-halflings-regular.eot b/plugins/web_gui/static/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..423bd5d3a20b804f596e04e5cd02fb4f16cfcbc1 GIT binary patch literal 20290 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/web_gui/static/fonts/glyphicons-halflings-regular.ttf b/plugins/web_gui/static/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a498ef4e7c8b556fc36f580c5ff524025bb11c84 GIT binary patch literal 41236 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 VT!1}Ptu549TOm(@MS}nTO#rGvU~d2b literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/images/bullet.gif b/plugins/web_gui/static/images/bullet.gif new file mode 100644 index 0000000000000000000000000000000000000000..c301719d7018b2c988b964bdbd3c8d96108e2e79 GIT binary patch literal 281 zcmZ?wbhEHbR9%a z?XESe#DDzyyzzATpT9qwHYhDR6+Hih|I90nK zLTlqXh10heFFBYn`-o@B5}u#GzkdJu;q2WNO>0#4TGf)F4{$v3g zqXQyAeqvxVbC^=#p(E9QVo8yNmWXB_Pg=5+mXJD&hl0pNEkVxo4-Te$6V4ym#K7Ur S#-?Z>#bhPkpC-w|U=0A_*%WBc~)&z?Q|{{8#gw{Op$J-c(~P9Gni zef##^zI}W8^yz2LoY}Eshp(^i{rmT)O`G=P#}A-h20}pbCkrD3g9w8TNFm5h2G(8$ z)jkK#9t}>OHv!8Q9S|!y$hGovYCM5*{6@|7v)oXNgSSs0g8QIxc_>)Dvc({ct*?HMH`TV;W u`8haSTRC}Hriw64pUKI|%|G8&c@Y=Oy7?srT?||T+w?cNsTn9TSOWm6w_FSW literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/images/comment.gif b/plugins/web_gui/static/images/comment.gif new file mode 100644 index 0000000000000000000000000000000000000000..951082f93a4bb0b7401e9cabdaaea9606cadb3f2 GIT binary patch literal 364 zcmZ?wbhEHb6krfwxT?&!0cPef##kd-qeZ`j)~xC4>$`UC+N4R7+S=N_eEG6t$Bw5@pPoN|{?VgH4<0-?apJ_|$B*yd zzkl%H!QS59zkmN$RaM=(b?e8EA9Lo+$Z8A}F?QAS8T!J3FOpN6dCh_oaF;8P^ zk!qjB&%-}Ic{>2~v3&%M* zj#H=+M93LVhU3T==s#=v{H!aROeP3|0G{VTkZvs&3mDGktXZs9gwt6xwY1hS!Wp;X z^?K3M(*s$SAxRPffq-rq&hjvRcb|gZD=8zFjVsL0IBjihh(sbtrBVoo!?4+Gh{xkP zE;P3wJ~{zOQDHvM$8xg9G)ALQB$G)5gF&5JC=?Kj#gNTrX?-4j18Iys-9~hHv~Ev~ zZ#J8e$zAo3#Y~0@2gteg3#i89uI=H%w(=K}(Mey}1a#RK7?>VxzCA7BvVU^v0R$jm6nz$D1XEXer(2tyD9BM<;x zi2$rDoM<9IIRT&$Gm1K4#=yiRK@=g78UJrF@BkGu2{H>Z*fYE>*}NdEeL{4D*6D@| L2rIxW{{J@tj9Vv} literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/images/page.gif b/plugins/web_gui/static/images/page.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c49ba877f0cdd497b308ee97f14aea8a7ea2448 GIT binary patch literal 393 zcmZ?wbhEHb6krfwxT?nR|NsA6w{AUr`0&S%A6KtleevSO!Gi}se*F0L>({+|_Z~QK z;NHD^ZEbB86%|jOJlVQ+>*L3dPn*L3dfBN+4%aH)={EQ|~cY79Cc zBSC&*U|Z(UP~agmtFOUd!QnsyPk)9dlLMO_yNj5hm5h_1o2Y<=$hq{6!-gF#tu2lR z7p#ze(Ol!)F>$>jQ)8nDb2Wp4G^-?6IhPnGCu6G z_|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?$=J}u$;8Rn(#aec>aNC)29{=)hHe(dmc~Y= zE*2Iry)OC5rManjB{01y2)!ma^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeal6G3r+HAl zDY)HYgj26R&@uX;h((HMm=G}afSB-P3*^8Perg^twHE=Cb=kgG>lqjr&v?2xhE&{o zGQ-#Fu!G3)&kMIsTN1hRBZpINHN)NpYxA}999{^rxPD;CV`=8dTXmNs@5o&7fY)9z zFIGuU|GS`tW9|P&ou(USs%LuYSbVsB#%FT;{n<139GT;{{FsgD=^2}+O`X8)cR;#= zLHdgPtW8svdSps&akRbmo%Nf~=M+cjE9pJ@P1D}g zac|;0!lCM_c5hnF?J!}bHHwPGtXV7{Pp?rvGSN~;towT;*TxjDrIY+m)v?Qp zS2}xHq_d9X_0rmNI}i2>c(ZLt*&!%obbZ0BsXXdVJ5K~CPnpdV`a(lrGVA9?&l$zb zoZGa%IL^4tFm+E0-vI}s*$J+%S)nQ^>O%7$fQ6ZB8mTU_+wojY0HPNHfB=ps?0F5mrxxZC*E%3Au3Y#+j zTgBxic>)_VW>50C`|PjQ+$sCG|Lpv`|Hq94m#>#CBSfb&Ecdv+aa!*B3)2ot{a~@p iWq-W?f73VJ0}Kb{-&m}6D&GMr>pWfkT-G@yGywnuqwe(p literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/img/chevron-right.png b/plugins/web_gui/static/img/chevron-right.png new file mode 100644 index 0000000000000000000000000000000000000000..61de8865bf010a083e22408c727adbd9626c1195 GIT binary patch literal 1442 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?$<@HZ+{n$?(#aec>aNC4rmn`WrcOqd&PHzL zMoy+My)OC5rManjB{01y2)!ma^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeal6G3r+HAl zDY)HYgj26R&@uX;h((HMm=G}afSB-P3*^8Perg^twHE=C_2X4f@);PI#5`RbLn>~) znQ_{SDNy3Ltf`bs!5)_i@63y<#5r!2-@VH165_^xVV&!Gfs&isIGxNJqXKr{Q(WYm zcdWOospH|=|DA>|&p-9fn;BE`;P{I4XCFRW-#=6HoMUg?c|+f`FK29W6OCfxf53dF zsd9A-%U;dkU(*iSPGH+*caTrx6`vkQP3x|^c`WVE6(u)Kx%~2pb?St>>_U^n6giC) z)?7Sq-!7miXi?(P#KW=rYq9vD{d<^o*K$a>c2x(N&-N|5!8ZLsuE8}Azs^M`!dG0( z_+sCu`t)PP53Z}PzaCs4{h&)@D|gEJ>!)qo*-kczWC#~&@haUZUJ<=;IkU9#GQ zH0PgJFBV=EwmK?S`oS!P&;(0W&q-%oR|Ktm5xbi&Z$(g}gTu4A&WCN9ln)ha9h?{Z zw8%1NYe4*~2^yt|;kI8`&T%|nJH=~hq;<=q2Q3A0h9X?Gk-A4xj1In#$7`fm?!ySuq&eBthPMJh%IrmP;H4;&jFPs&n)2KdmA&2aP2^+lICOH?Eoszib zJl8KhG}0~mE?fh}=O2-9li}do_0=g5JDyQy?KbBQhdgg#u3BO1K&%J}Q z4t9NGcd|8YN=Rxwxh+BLptSb(|0&kb>e+eUMmI1rB!9Ag94~OD0aR*wy85}Sb4q9e E05!%6pa1{> literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/img/devoops_getdata.gif b/plugins/web_gui/static/img/devoops_getdata.gif new file mode 100644 index 0000000000000000000000000000000000000000..891304ad26e0ec88696ef75a995abd2d9b6c582d GIT binary patch literal 2892 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 h(J5^}y^tW9gzF|Zu6%!1{fY5^_cK-kzHu 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 Sp#SgRYMN@gs#VIium20kP#JFk literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/img/logo-200.png b/plugins/web_gui/static/img/logo-200.png new file mode 100644 index 0000000000000000000000000000000000000000..551b91c8b7c5ed9ed44574a6a3c5f2e35aa69f9b GIT binary patch literal 2872 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 OH!?dht-iWF|L_m~ zH$YKTqByCQ$#{l*L-Bs{|GgtzB*R&pui_b0$4$eB)P#j<5ELC_4wj)|EiZnAV-yvm z?Mf9_^(omz4r4?ZCUiW)rl_&;&@;?=h(Qg`*{(wWeEW_Dwx!Us8J*KT6*lb26(7#5 zOjpd6c~i3J@ylQ=l!<@?u>nG7!42e4pl_ZE{uDwN*kqaV4qlT8SLX%7nj^KD*SvP2xi4=?t z4Ugp+E;>>NsO$fSI!+fI;4(bS_n*Q+W!Zyl83t&{H%a5_!%-+tR()t-OYsSZ~|=8^+l+~Hb>+-y&7WCh0~ku~Vsx1d$Fz) zGoD>P_H=7|JO1M3-6zM_p090g-+uU|Qu?vQ4SBKMYmc}KdqX!)iVxh8_|YS~?D_sX zR4woaKS1v575wdSZRE{+FE*MvUH_$8u~mM3QFwMDq4pgaq^{rpL@D1lxacw#^V8a^ I+|7G`0IGFBUjP6A literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/img/sort.png b/plugins/web_gui/static/img/sort.png new file mode 100644 index 0000000000000000000000000000000000000000..337ff81f9083e87e82f6d3f62fe64edacf629b96 GIT binary patch literal 1060 zcmaJ=TSyd97#;|_7>0=k_B4(tO6|;?y}2{EiM!)v%Q0COTzbiI=IBm3bHmf?0CW|&TCpKjuc0nT#|)(h#-XAO_P>C& z6t#!Z6G@zuTSOHZtm0zWjA0QrMb*}2EJf{wnC^l-x*29RmY*=Ru7#P7fXvHQ6sGj% zAse<2wI?d5@&%JToAhOvWoa2)RD`%hsfF=#<94jnXLtE6$=Cm#t!33Ss1=kVQw^gLGAgZfYp)RBz&CS&W$uR!kMfq%cDiSY6jd$rlI#zYrAs zyZ}IhFX9b_gs3;<^8r5qk@_rGLh674O`PRwyWE_ZPqJ zELekcFW;?1E`BsFADo}{fvz~a2>NIJmBUw0O^IbcZ{5Cm=h;S4!vq-PDnd^y2U@CD z&y~j3^M2&DM5d<~r^c+i3&|Dk-r1?sbC0XowMo9||k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?+1%35!qvdo(#aec>aNC4POh#NCKit7F2-&K zZm#Aqy)OC5rManjB{01y2)!ma^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeal6G3r+HAl zDY)HYgj26R&@uX;h((HMm=G}afSB-P3*^8Perg^twHE=Cb$nvVF9rrC4o?@ykcwMx zrf>8*>>zP`_O&1l#VKVg?lw(M5dUggVi*xq%j{b4ol$GYO8yIcLE`L=;q3Pn{4On& zk_qz8;a+O;wf-Sf<_XpE%n3@CKMHg8uK)S*?%nU8OuPB%VJlOOwXX#&40*A><=X+} z9ju{^_op9JtzbGHV|-#G|DkQU)0ICk+G*-9cqN&x*vx+3=8)v;N~A<#X9DcMN1B)+$o!Q{&{{&i`wLq#=F*b zh<^9}cw$1DC|B#*1&yZHc-EBnJ7+MLthmw<+_q)jhe^Echf7PoJ3Osm=)7XSyoZx7 zHL^}vXp>HNiK!H$=|U6d6sfL7FAfPx@vyx+zGR8a%%GJ^+V36_dG-DGz4fQPERCKP zMfT5KS<88vLF$E@>NWwmdNE^J#9~3;X@c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkcW@2jT>SAncX>Mw6Xy|I}Xl`cgW@+kb=xAnU zW^CXF)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GSs&<Gadh9E-^t^<0ENqH;M>Qr{tE!ekIgUx|glO^b)2Uk3kA-mpL z3AP6YERsG9tKyr?Wf?@jFt1FFF!6V}&eQKE6Bx#FBz=K}*mNtmno7nOvi1sJSy!aV h`oLWN<6$z**UXRGo_2AxP?SCrm+E?LY7c zR#B9P*3ucAk#-6S(gU)K2{^h**c4S&U$GUKpI zYaFm(>p*i_8R%A`DqT|zsvLm`=n%`m(R&PAaANeFu0ZDQHba9s2=0#2^GRi-77#}k z1d%|&rKZ0&9 z${O}UnMlDHM>ZKY5Oj}}14`2Wp}M|^ws8vn$@ibacDmn$ObXhl*HTF1I!fJ8rVzKF zjFFW_s3%v&mM(;m-GxjLZ{w{{8g>*1? zWI@ZH3!7JOfve`vh0DujNHUDu*uNT`+am69r;D~Fi$&u@gSg!ywjMrr`zyH;50heD z+IiXjV|KR2vvqLA@PnzTt4k(d4LX9?Uae52H;V^Hrak3*%f7AgzN6mUTm7*B+&VEi z?U^aBjo(hPVHq)$ literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/img/ui-left.png b/plugins/web_gui/static/img/ui-left.png new file mode 100644 index 0000000000000000000000000000000000000000..dd7e49f84f09395118a1d96fd1197b90a03b128d GIT binary patch literal 1085 zcmaJ=U1-x#7)=?IIT&s*)QR9VMO3g!)3vb;jqBQUwrb|=3acn%X>zxQEx9qdwcVJa zPR9B$@Ig=%L}k7T6QA_K3H1+@DLzen7JO3JYh~VS>-51IlH4E8Ip24`@7&5j|M9lg zJ*^Z)wWU*1hK%j**RqZL_pPoeWaz@l93DiYxTM&S>eWylg0!KG!3842kc>aP0x+c;?A=xim30TlmQ#Kr& z>d&fE<7z~sdyau^=-x?E0Hc>YzZt|DwUX0 zH-qdkmWxCpu0|l>BM6@}X=0`9GaYYTL4uBI>lW6L30y@bkBV5NNv0b|FsvxQy~gbfvp>?}eP z^(qb&5JpY`Ss*dUgF{2QsiBf{cpWdxLfUk&VyZALi8N7QbX^l7JTJxL34i2hfakbm zcRZZr!$FP@^9imm%!le+38_T`nz+u@{&2a5T-OSQMIuYk)-OV>&qfAVKeC`V%q5;| zsJF@08s-x3Ysh6uGOXL!zZzZNBJOdgTec;OE#pIzxZNhUe)-D#lU#|#wA7m|f63R@ z)_R%_T&bjrE3xU8xtWg#c2}%kPy3tL%G!h3=xq8)`^WPw)laF~tyt||j=evA*;D-< zt2LkPV0LwSE_CkvaJsTxdKgl>mv+djC#UZ$cKvLgU-neLE-cJkibXpr%R8!{ujb}& zUVnPKGhrpYZ*Ocb%)Y1c#mrzn7!;S54i-+-ViUu;*6Od+Gy}d#XFRs2BiuPR)U+r* f+v|O_(gl{N^RLg{9cK5BxEDH|?3W(LN3Q(_SX^K- literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/img/ui-right.png b/plugins/web_gui/static/img/ui-right.png new file mode 100644 index 0000000000000000000000000000000000000000..dba43d67926337a853f43b93e74864aba012daa8 GIT binary patch literal 1104 zcmaJ=TWHfz7>?FW-9@UP&I_1jh#T0XN!QGVb!*qOT4v_x3id(4G&x(tmYkTJ*=!&b zQQQWCh&MLyO?^?TZ&L?~^hHomlsPXCGJNty)E5P1p3HUnU=2ymh41_R|NQ@V#(R7A z*4J#UAqb*Axlc^t(d&L|s_}ov*9935TTncM`d~lG%N8J_D$D{hsmlW(1!Q&P=wr}M z5FScPXHZ7kFDOu_Wfwy`x{28Y(cbBpvN8w|nFRxy5vD%fe?XC%8m0~gCBJ0GKu+5? zYJtAdp0qMLsDxCivx97R1T3HfB$JLlWY~ferWSPtJa@Mlid=-C!7%kZsf^T1#-Ihr zARX{2ewHP9o@QHvJkRbXIX}xWe*E%2wp9r70@p?^Jrs^+sr^DqOf1F1t1y*A$P^eR zpU>0z01d4Hh7E;6t_H{XFv4e#7)W+}hTT+F5P_{&nu#=MkglSfg~KRJ;Y@!YK{uCW z4ST6fxL}MUn+!|)-6NHOlJtM5t}ml)lmdV9{im><9x(xv0yZ4B6x_J}CO4ER#4I2q zXr&<>Dp#>L2NAS$&?IAhJlT9uGgO$jTNd$>BqR+R$%X=wVwl1Tw5F+o$cMyeA{Yp@ zaXib$10j)(#e#`ww5`?Oy=yM=9i^xTyT_)3(LVl?f% z$^KYa==AI?tUXg)QF>c&1h2hbA(|#@XFYdzpFh5K%r1P})%6bLgT$KK zD_Lf8t}Rb!{;hb9gL8VV_D!^Nukc;sDOX((r9*ruzmw~!Bs)y2bw?&9-V_l_syJ>spdBPV_V DZ>4B< literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/index.html b/plugins/web_gui/static/index.html new file mode 100644 index 0000000..fe12fa9 --- /dev/null +++ b/plugins/web_gui/static/index.html @@ -0,0 +1,126 @@ + + + + + StarryPy + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+ preloader +
+
+
+ +
+
+ + + + + + + + diff --git a/plugins/web_gui/static/js/bootstrap-sortable.js b/plugins/web_gui/static/js/bootstrap-sortable.js new file mode 100644 index 0000000..d23d884 --- /dev/null +++ b/plugins/web_gui/static/js/bootstrap-sortable.js @@ -0,0 +1,129 @@ +/* TINY SORT modified according to this https://github.com/Sjeiti/TinySort/pull/51*/ +(function (e, t) { function h(e) { return e && e.toLowerCase ? e.toLowerCase() : e } function p(e, t) { for (var r = 0, i = e.length; r < i; r++) if (e[r] == t) return !n; return n } var n = !1, r = null, i = parseFloat, s = Math.min, o = /(-?\d+\.?\d*)$/g, u = /(\d+\.?\d*)$/g, a = [], f = [], l = function (e) { return typeof e == "string" }, c = Array.prototype.indexOf || function (e) { var t = this.length, n = Number(arguments[1]) || 0; n = n < 0 ? Math.ceil(n) : Math.floor(n); if (n < 0) n += t; for (; n < t; n++) { if (n in this && this[n] === e) return n } return -1 }; e.tinysort = { id: "TinySort", version: "1.5.2", copyright: "Copyright (c) 2008-2013 Ron Valstar", uri: "http://tinysort.sjeiti.com/", licensed: { MIT: "http://www.opensource.org/licenses/mit-license.php", GPL: "http://www.gnu.org/licenses/gpl.html" }, plugin: function () { var e = function (e, t) { a.push(e); f.push(t) }; e.indexOf = c; return e }(), defaults: { order: "asc", attr: r, data: r, useVal: n, place: "start", returns: n, cases: n, forceStrings: n, ignoreDashes: n, sortFunction: r } }; e.fn.extend({ tinysort: function () { var d, v, m = this, g = [], y = [], b = [], w = [], E = 0, S, x = [], T = [], N = function (t) { e.each(a, function (e, n) { n.call(n, t) }) }, C = function (t, r) { var s = 0; if (E !== 0) E = 0; while (s === 0 && E < S) { var a = w[E], c = a.oSettings, p = c.ignoreDashes ? u : o; N(c); if (c.sortFunction) { s = c.sortFunction(t, r) } else if (c.order == "rand") { s = Math.random() < .5 ? 1 : -1 } else { var d = n, v = !c.cases ? h(t.s[E]) : t.s[E], m = !c.cases ? h(r.s[E]) : r.s[E]; v = v.replace(/^\s*/i, "").replace(/\s*$/i, ""); m = m.replace(/^\s*/i, "").replace(/\s*$/i, ""); if (!A.forceStrings) { var g = l(v) ? v && v.match(p) : n, y = l(m) ? m && m.match(p) : n; if (g && y) { var b = v.substr(0, v.length - g[0].length), x = m.substr(0, m.length - y[0].length); if (b == x) { d = !n; v = i(g[0]); m = i(y[0]) } } } s = a.iAsc * (v < m ? -1 : v > m ? 1 : 0) } e.each(f, function (e, t) { s = t.call(t, d, v, m, s) }); if (s === 0) E++ } return s }; for (d = 0, v = arguments.length; d < v; d++) { var k = arguments[d]; if (l(k)) { if (x.push(k) - 1 > T.length) T.length = x.length - 1 } else { if (T.push(k) > x.length) x.length = T.length } } if (x.length > T.length) T.length = x.length; S = x.length; if (S === 0) { S = x.length = 1; T.push({}) } for (d = 0, v = S; d < v; d++) { var L = x[d], A = e.extend({}, e.tinysort.defaults, T[d]), O = !(!L || L == ""), M = O && L[0] == ":"; w.push({ sFind: L, oSettings: A, bFind: O, bAttr: !(A.attr === r || A.attr == ""), bData: A.data !== r, bFilter: M, $Filter: M ? m.filter(L) : m, fnSort: A.sortFunction, iAsc: A.order == "asc" ? 1 : -1 }) } m.each(function (n, r) { var i = e(r), s = i.parent().get(0), o, u = []; for (j = 0; j < S; j++) { var a = w[j], f = a.bFind ? a.bFilter ? a.$Filter.filter(r) : i.find(a.sFind) : i; u.push(a.bData ? f.data(a.oSettings.data) : a.bAttr ? f.attr(a.oSettings.attr) : a.oSettings.useVal ? f.val() : f.text()); if (o === t) o = f } var l = c.call(b, s); if (l < 0) { l = b.push(s) - 1; y[l] = { s: [], n: [] } } if (o.length > 0) y[l].s.push({ s: u, e: i, n: n }); else y[l].n.push({ e: i, n: n }) }); e.each(y, function (e, t) { t.s.sort(C) }); e.each(y, function (t, r) { var i = r.s.length, o = [], u = i, a = [0, 0]; switch (A.place) { case "first": e.each(r.s, function (e, t) { u = s(u, t.n) }); break; case "org": e.each(r.s, function (e, t) { o.push(t.n) }); break; case "end": u = r.n.length; break; default: u = 0 } for (d = 0; d < i; d++) { var f = p(o, d) ? !n : d >= u && d < u + r.s.length, l = (f ? r.s : r.n)[a[f ? 0 : 1]].e; l.parent().append(l); if (f || !A.returns) g.push(l.get(0)); a[f ? 0 : 1]++ } }); m.length = 0; Array.prototype.push.apply(m, g); return m } }); e.fn.TinySort = e.fn.Tinysort = e.fn.tsort = e.fn.tinysort })(jQuery); + +(function ($) { + + var $document = $(document), + bsSort = [], + lastSort, + signClass; + + $.bootstrapSortable = function (applyLast, sign) { + + // check if moment.js is available + var momentJsAvailable = (typeof moment !== 'undefined'); + + //Set class based on sign parameter + signClass = !sign ? "arrow" : sign; + + // set attributes needed for sorting + $('table.sortable').each(function () { + var $this = $(this); + applyLast = (applyLast === true); + $this.find('span.sign').remove(); + $this.find('thead tr').each(function (rowIndex) { + var columnsSkipped = 0; + $(this).find('th').each(function (columnIndex) { + var $this = $(this); + $this.attr('data-sortcolumn', columnIndex + columnsSkipped); + $this.attr('data-sortkey', columnIndex + '-' + rowIndex); + if ($this.attr("colspan") !== undefined) { + columnsSkipped += parseInt($this.attr("colspan")) - 1; + } + }); + }); + $this.find('td').each(function () { + var $this = $(this); + if ($this.attr('data-dateformat') != undefined && momentJsAvailable) { + $this.attr('data-value', moment($this.text(), $this.attr('data-dateformat')).format('YYYY/MM/DD/HH/mm/ss')); + } + else { + $this.attr('data-value') === undefined && $this.attr('data-value', $this.text()); + } + }); + $this.find('thead th[data-defaultsort!="disabled"]').each(function (index) { + var $this = $(this); + var $sortTable = $this.closest('table.sortable'); + $this.data('sortTable', $sortTable); + var sortKey = $this.attr('data-sortkey'); + var thisLastSort = applyLast ? lastSort : -1; + bsSort[sortKey] = applyLast ? bsSort[sortKey] : $this.attr('data-defaultsort'); + if (bsSort[sortKey] != null && (applyLast == (sortKey == thisLastSort))) { + bsSort[sortKey] = bsSort[sortKey] == 'asc' ? 'desc' : 'asc'; + doSort($this, $sortTable) + } + }); + $this.trigger('sorted'); + }); + }; + + // add click event to table header + $document.on('click', 'table.sortable thead th[data-defaultsort!="disabled"]', function (e) { + var $this = $(this), $table = $this.data('sortTable') || $this.closest('table.sortable'); + doSort($this, $table); + $table.trigger('sorted'); + }); + + //Sorting mechanism separated + function doSort($this, $table) { + var sortColumn = $this.attr('data-sortcolumn'); + + var colspan = $this.attr('colspan'); + if (colspan) { + var selector; + for (var i = parseFloat(sortColumn) ; i < parseFloat(sortColumn) + parseFloat(colspan) ; i++) { + selector = selector + ', [data-sortcolumn="' + i + '"]'; + } + var subHeader = $(selector).not('[colspan]'); + var mainSort = subHeader.filter('[data-mainsort]').eq(0); + + sortColumn = mainSort.length ? mainSort : subHeader.eq(0); + doSort(sortColumn, $table); + return; + } + + //sortColumn = newColumn ? newColumn : sortColumn; + + var localSignClass = $this.attr('data-defaultsign') || signClass; + // update arrow icon + if ($.browser.mozilla) { + var moz_arrow = $table.find('div.mozilla'); + if (moz_arrow != null) { + moz_arrow.parent().html(moz_arrow.text()); + } + $this.wrapInner('
'); + $this.children().eq(0).append(''); + } + else { + $table.find('span.sign').remove(); + $this.append(''); + } + + // sort direction + + var sortKey = $this.attr('data-sortkey'); + + lastSort = sortKey; + bsSort[sortKey] = bsSort[sortKey] == 'asc' ? 'desc' : 'asc'; + if (bsSort[sortKey] == 'desc') { $this.find('span.sign').addClass('up'); } + + // sort rows + var rows = $table.find('tbody tr'); + rows.tsort('td:eq(' + sortColumn + ')', { order: bsSort[sortKey], attr: 'data-value' }); + } + + // jQuery 1.9 removed this object + if (!$.browser) { + $.browser = { chrome: false, mozilla: false, opera: false, msie: false, safari: false }; + var ua = navigator.userAgent; + $.each($.browser, function (c) { + $.browser[c] = ((new RegExp(c, 'i').test(ua))) ? true : false; + if ($.browser.mozilla && c == 'mozilla') { $.browser.mozilla = ((new RegExp('firefox', 'i').test(ua))) ? true : false; } + if ($.browser.chrome && c == 'safari') { $.browser.safari = false; } + }); + } + + // Initialise on DOM ready + $($.bootstrapSortable); + +}(jQuery)); diff --git a/plugins/web_gui/static/js/devoops.min.js b/plugins/web_gui/static/js/devoops.min.js new file mode 100644 index 0000000..be8b8dc --- /dev/null +++ b/plugins/web_gui/static/js/devoops.min.js @@ -0,0 +1 @@ +"use strict";function LoadCalendarScript(callback){function LoadFullCalendarScript(){if(!$.fn.fullCalendar)$.getScript('plugins/fullcalendar/fullcalendar.js',callback);else if(callback&&typeof callback==="function")callback();}if(!$.fn.moment)$.getScript('plugins/moment/moment.min.js',LoadFullCalendarScript);else LoadFullCalendarScript();}function LoadOpenLayersScript(callback){if(!$.fn.OpenLayers)$.getScript('http://www.openlayers.org/api/OpenLayers.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadTimePickerScript(callback){if(!$.fn.timepicker)$.getScript('plugins/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.min.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadBootstrapValidatorScript(callback){if(!$.fn.bootstrapValidator)$.getScript('plugins/bootstrapvalidator/bootstrapValidator.min.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadSelect2Script(callback){if(!$.fn.select2)$.getScript('plugins/select2/select2.min.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadDataTablesScripts(callback){function LoadDatatables(){$.getScript('plugins/datatables/jquery.dataTables.js',function(){$.getScript('plugins/datatables/ZeroClipboard.js',function(){$.getScript('plugins/datatables/TableTools.js',function(){$.getScript('plugins/datatables/dataTables.bootstrap.js',callback);});});});}if(!$.fn.dataTables)LoadDatatables();else if(callback&&typeof callback==="function")callback();}function LoadFineUploader(callback){if(!$.fn.fineuploader)$.getScript('plugins/fineuploader/jquery.fineuploader-4.3.1.min.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadXChartScript(callback){function LoadXChart(){$.getScript('plugins/xcharts/xcharts.min.js',callback);}function LoadD3Script(){if(!$.fn.d3)$.getScript('plugins/d3/d3.v3.min.js',LoadXChart);else LoadXChart();}if(!$.fn.xcharts)LoadD3Script();else if(callback&&typeof callback==="function")callback();}function LoadFlotScripts(callback){function LoadFlotScript(){$.getScript('plugins/flot/jquery.flot.js',LoadFlotResizeScript);}function LoadFlotResizeScript(){$.getScript('plugins/flot/jquery.flot.resize.js',LoadFlotTimeScript);}function LoadFlotTimeScript(){$.getScript('plugins/flot/jquery.flot.time.js',callback);}if(!$.fn.flot)LoadFlotScript();else if(callback&&typeof callback==="function")callback();}function LoadMorrisScripts(callback){function LoadMorrisScript(){if(!$.fn.Morris)$.getScript('plugins/morris/morris.min.js',callback);else if(callback&&typeof callback==="function")callback();}if(!$.fn.raphael)$.getScript('plugins/raphael/raphael-min.js',LoadMorrisScript);else LoadMorrisScript();}function LoadFancyboxScript(callback){if(!$.fn.fancybox)$.getScript('plugins/fancybox/jquery.fancybox.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadKnobScripts(callback){if(!$.fn.knob)$.getScript('plugins/jQuery-Knob/jquery.knob.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadSparkLineScript(callback){if(!$.fn.sparkline)$.getScript('plugins/sparkline/jquery.sparkline.min.js',callback);else if(callback&&typeof callback==="function")callback();}function LoadAjaxContent(url){$('.preloader').show();$.ajax({mimeType:'text/html; charset=utf-8',url:url,type:'GET',success:function(data){$('#ajax-content').html(data);$('.preloader').hide();},error:function(jqXHR,textStatus,errorThrown){alert(errorThrown);},dataType:"html",async:false});}function WinMove(){$("div.box").not('.no-drop').draggable({revert:true,zIndex:2000,cursor:"crosshair",handle:'.box-name',opacity:0.8}).droppable({tolerance:'pointer',drop:function(event,ui){var draggable=ui.draggable;var droppable=$(this);var dragPos=draggable.position();var dropPos=droppable.position();draggable.swap(droppable);setTimeout(function(){var dropmap=droppable.find('[id^=map-]');var dragmap=draggable.find('[id^=map-]');if(dragmap.length>0||dropmap.length>0){dragmap.resize();dropmap.resize();}else{draggable.resize();droppable.resize();}},50);setTimeout(function(){draggable.find('[id^=map-]').resize();droppable.find('[id^=map-]').resize();},250);}});}jQuery.fn.swap=function(b){b=jQuery(b)[0];var a=this[0];var t=a.parentNode.insertBefore(document.createTextNode(''),a);b.parentNode.insertBefore(a,b);t.parentNode.insertBefore(b,t);t.parentNode.removeChild(t);return this;};function ScreenSaver(){var canvas=document.getElementById("canvas");var ctx=canvas.getContext("2d");var W=window.innerWidth;var H=window.innerHeight;canvas.width=W;canvas.height=H;var particles=[];for(var i=0;i<25;i++)particles.push(new Particle());function Particle(){this.location={x:Math.random()*W,y:Math.random()*H};this.radius=0;this.speed=3;this.angle=Math.random()*360;var r=Math.round(Math.random()*255);var g=Math.round(Math.random()*255);var b=Math.round(Math.random()*255);var a=Math.random();this.rgba="rgba("+r+", "+g+", "+b+", "+a+")";}function draw(){ctx.globalCompositeOperation="source-over";ctx.fillStyle="rgba(0, 0, 0, 0.02)";ctx.fillRect(0,0,W,H);ctx.globalCompositeOperation="lighter";for(var i=0;iW)p.location.x=0;if(p.location.y<0)p.location.y=H;if(p.location.y>H)p.location.y=0;}}setInterval(draw,30);}function drawGoogleChart(chart_data,chart_options,element,chart_type){var data=google.visualization.arrayToDataTable(chart_data);var chart=new chart_type(document.getElementById(element));chart.draw(data,chart_options);}function DrawKnob(elem){elem.knob({change:function(value){},release:function(value){console.log("release : "+value);},cancel:function(){console.log("cancel : ",this);},draw:function(){if(this.$.data('skin')=='tron'){var a=this.angle(this.cv);var sa=this.startAngle;var sat=this.startAngle;var ea;var eat=sat+a;var r=1;this.g.lineWidth=this.lineWidth;this.o.cursor&&(sat=eat-0.3)&&(eat=eat+0.3);if(this.o.displayPrevious){ea=this.startAngle+this.angle(this.v);this.o.cursor&&(sa=ea-0.3)&&(ea=ea+0.3);this.g.beginPath();this.g.strokeStyle=this.pColor;this.g.arc(this.xy,this.xy,this.radius-this.lineWidth,sa,ea,false);this.g.stroke();}this.g.beginPath();this.g.strokeStyle=r?this.o.fgColor:this.fgColor;this.g.arc(this.xy,this.xy,this.radius-this.lineWidth,sat,eat,false);this.g.stroke();this.g.lineWidth=2;this.g.beginPath();this.g.strokeStyle=this.o.fgColor;this.g.arc(this.xy,this.xy,this.radius-this.lineWidth+1+this.lineWidth*2/3,0,2*Math.PI,false);this.g.stroke();return false;}}});var v;var up=0;var down=0;var i=0;var $idir=$("div.idir");var $ival=$("div.ival");var incr=function(){i++;$idir.show().html("+").fadeOut();$ival.html(i);};var decr=function(){i--;$idir.show().html("-").fadeOut();$ival.html(i);};$("input.infinite").knob({min:0,max:20,stopper:false,change:function(){if(v>this.cv)if(up){decr();up=0;}else{up=1;down=0;}else if(v1)map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':true}));map.addControl(new OpenLayers.Control.Permalink());map.addControl(new OpenLayers.Control.MousePosition({displayProjection:epsg4326}));return map;}function PrettyDates(){var currDate=new Date();var year=currDate.getFullYear();var month=currDate.getMonth()+1;var startmonth=1;if(month>3)startmonth=month-2;if(startmonth<=9)startmonth='0'+startmonth;if(month<=9)month='0'+month;var day=currDate.getDate();if(day<=9)day='0'+day;var startdate=year+'-'+startmonth+'-01';var enddate=year+'-'+month+'-'+day;return [startdate,enddate];}function SetMinBlockHeight(elem){elem.css('min-height',window.innerHeight-49);}function MessagesMenuWidth(){var W=window.innerWidth;var W_menu=$('#sidebar-left').outerWidth();var w_messages=(W-W_menu)*16.666666666666664/100;$('#messages-menu').width(w_messages);}function DashboardTabChecker(){$('#content').on('click','a.tab-link',function(e){e.preventDefault();$('div#dashboard_tabs').find('div[id^=dashboard]').each(function(){$(this).css('visibility','hidden').css('position','absolute');});var attr=$(this).attr('id');$('#'+'dashboard-'+attr).css('visibility','visible').css('position','relative');$(this).closest('.nav').find('li').removeClass('active');$(this).closest('li').addClass('active');});}function TinyMCEStart(elem,mode){var plugins=[];if(mode=='extreme')plugins=["advlist anchor autolink autoresize autosave bbcode charmap code contextmenu directionality ","emoticons fullpage fullscreen hr image insertdatetime layer legacyoutput","link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace","tabfocus table template textcolor visualblocks visualchars wordcount"];tinymce.init({selector:elem,theme:"modern",plugins:plugins,toolbar:"insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | print preview media fullpage | forecolor backcolor emoticons",style_formats:[{title:'Header 2',block:'h2',classes:'page-header'},{title:'Header 3',block:'h3',classes:'page-header'},{title:'Header 4',block:'h4',classes:'page-header'},{title:'Header 5',block:'h5',classes:'page-header'},{title:'Header 6',block:'h6',classes:'page-header'},{title:'Bold text',inline:'b'},{title:'Red text',inline:'span',styles:{color:'#ff0000'}},{title:'Red header',block:'h1',styles:{color:'#ff0000'}},{title:'Example 1',inline:'span',classes:'example1'},{title:'Example 2',inline:'span',classes:'example2'},{title:'Table styles'},{title:'Table row 1',selector:'tr',classes:'tablerow1'}]});}function SparkLineDrawBarGraph(elem,arr,color){if(color)var stacked_color=color;else stacked_color='#6AA6D6';elem.sparkline(arr,{type:'bar',barWidth:7,highlightColor:'#000',barSpacing:2,height:40,stackedBarColor:stacked_color});}function OpenModalBox(header,inner,bottom){var modalbox=$('#modalbox');modalbox.find('.modal-header-name span').html(header);modalbox.find('.devoops-modal-inner').html(inner);modalbox.find('.devoops-modal-bottom').html(bottom);modalbox.fadeIn('fast');$('body').addClass("body-expanded");}function CloseModalBox(){var modalbox=$('#modalbox');modalbox.fadeOut('fast',function(){modalbox.find('.modal-header-name span').children().remove();modalbox.find('.devoops-modal-inner').children().remove();modalbox.find('.devoops-modal-bottom').children().remove();$('body').removeClass("body-expanded");});}(function($){$.fn.beautyTables=function(){var table=this;var string_fill=false;this.on('keydown',function(event){var target=event.target;var tr=$(target).closest("tr");var col=$(target).closest("td");if(target.tagName.toUpperCase()=='INPUT'){if(event.shiftKey===true)switch(event.keyCode){case 37:col.prev().children("input[type=text]").focus();break;case 39:col.next().children("input[type=text]").focus();break;case 40:if(string_fill==false)tr.next().find('td:eq('+col.index()+') input[type=text]').focus();break;case 38:if(string_fill==false)tr.prev().find('td:eq('+col.index()+') input[type=text]').focus();break;}if(event.ctrlKey===true)switch(event.keyCode){case 37:tr.find('td:eq(1)').find("input[type=text]").focus();break;case 39:tr.find('td:last-child').find("input[type=text]").focus();break;case 40:if(string_fill==false)table.find('tr:last-child td:eq('+col.index()+') input[type=text]').focus();break;case 38:if(string_fill==false)table.find('tr:eq(1) td:eq('+col.index()+') input[type=text]').focus();break;}if(event.keyCode==13||event.keyCode==9){event.preventDefault();col.next().find("input[type=text]").focus();}if(string_fill==false){if(event.keyCode==34){event.preventDefault();table.find('tr:last-child td:last-child').find("input[type=text]").focus();}if(event.keyCode==33){event.preventDefault();table.find('tr:eq(1) td:eq(1)').find("input[type=text]").focus();}}}});table.find("input[type=text]").each(function(){$(this).on('blur',function(event){var target=event.target;var col=$(target).parents("td");if(table.find("input[name=string-fill]").prop("checked")==true)col.nextAll().find("input[type=text]").each(function(){$(this).val($(target).val());});});});};})(jQuery);(function($){$.fn.beautyHover=function(){var table=this;table.on('mouseover','td',function(){var idx=$(this).index();var rows=$(this).closest('table').find('tr');rows.each(function(){$(this).find('td:eq('+idx+')').addClass('beauty-hover');});}).on('mouseleave','td',function(e){var idx=$(this).index();var rows=$(this).closest('table').find('tr');rows.each(function(){$(this).find('td:eq('+idx+')').removeClass('beauty-hover');});});};})(jQuery);function Table2Json(table){var result={};table.find("tr").each(function(){var oneRow=[];var varname=$(this).index();$("td",this).each(function(index){if(index!=0)oneRow.push($("input",this).val());});result[varname]=oneRow;});var result_json=JSON.stringify(result);OpenModalBox('Table to JSON values',result_json);}function FlotGraph1(){var data=[],totalPoints=300;function getRandomData(){if(data.length>0)data=data.slice(1);while(data.length0?data[data.length-1]:50,y=prev+Math.random()*10-5;if(y<0)y=0;else if(y>100)y=100;data.push(y);}var res=[];for(var i=0;iaxes.xaxis.max||pos.yaxes.yaxis.max)return;var i,j,dataset=plot.getData();for(i=0;ipos.x)break;var y,p1=series.data[j-1],p2=series.data[j];if(p1==null)y=p2[1];else if(p2==null)y=p1[1];else y=p1[1]+(p2[1]-p1[1])*(pos.x-p1[0])/(p2[0]-p1[0]);legends.eq(i).text(series.label.replace(/=.*/,"= "+y.toFixed(2)));}}$("#box-two-content").bind("plothover",function(event,pos,item){latestPosition=pos;if(!updateLegendTimeout)updateLegendTimeout=setTimeout(updateLegend,50);});}function FlotGraph3(){var d1=[];for(var i=0;i<=60;i+=1)d1.push([i,parseInt(Math.random()*30-10)]);function plotWithOptions(t){$.plot("#box-three-content",[{data:d1,color:"rgb(30, 180, 20)",threshold:{below:t,color:"rgb(200, 20, 30)"},lines:{steps:true}}]);}plotWithOptions(0);}function FlotGraph4(){var d1=[];for(var i=0;i<14;i+=0.5)d1.push([i,Math.sin(i)]);var d2=[[0,3],[4,8],[8,5],[9,13]];var d3=[];for(var i=0;i<14;i+=0.5)d3.push([i,Math.cos(i)]);var d4=[];for(var i=0;i<14;i+=0.1)d4.push([i,Math.sqrt(i*10)]);var d5=[];for(var i=0;i<14;i+=0.5)d5.push([i,Math.sqrt(i)]);var d6=[];for(var i=0;i<14;i+=0.5+Math.random())d6.push([i,Math.sqrt(2*i+Math.sin(i)+5)]);$.plot("#box-four-content",[{data:d1,lines:{show:true,fill:true}},{data:d2,bars:{show:true}},{data:d3,points:{show:true}},{data:d4,lines:{show:true}},{data:d5,lines:{show:true},points:{show:true}},{data:d6,lines:{show:true,steps:true}}]);}function MorrisChart1(){var day_data=[{"period":"2013-10-01","licensed":3407,"sorned":660},{"period":"2013-09-30","licensed":3351,"sorned":629},{"period":"2013-09-29","licensed":3269,"sorned":618},{"period":"2013-09-20","licensed":3246,"sorned":661},{"period":"2013-09-19","licensed":3257,"sorned":667},{"period":"2013-09-18","licensed":3248,"sorned":627},{"period":"2013-09-17","licensed":3171,"sorned":660},{"period":"2013-09-16","licensed":3171,"sorned":676},{"period":"2013-09-15","licensed":3201,"sorned":656},{"period":"2013-09-10","licensed":3215,"sorned":622}];Morris.Bar({element:'morris-chart-1',data:day_data,xkey:'period',ykeys:['licensed','sorned'],labels:['Licensed','SORN'],xLabelAngle:60});}function MorrisChart2(){Morris.Area({element:'morris-chart-2',data:[{x:'2011 Q1',y:3,z:3,m:1},{x:'2011 Q2',y:2,z:0,m:7},{x:'2011 Q3',y:2,z:5,m:2},{x:'2011 Q4',y:4,z:4,m:5},{x:'2012 Q1',y:6,z:1,m:11},{x:'2012 Q2',y:4,z:4,m:3},{x:'2012 Q3',y:4,z:4,m:7},{x:'2012 Q4',y:4,z:4,m:9}],xkey:'x',ykeys:['y','z','m'],labels:['Y','Z','M']}).on('click',function(i,row){console.log(i,row);});}function MorrisChart3(){var decimal_data=[];for(var x=0;x<=360;x+=10)decimal_data.push({x:x,y:Math.sin(Math.PI*x/180).toFixed(4),z:Math.cos(Math.PI*x/180).toFixed(4)});Morris.Line({element:'morris-chart-3',data:decimal_data,xkey:'x',ykeys:['y','z'],labels:['sin(x)','cos(x)'],parseTime:false,goals:[-1,0,1]});}function MorrisChart4(){Morris.Bar({element:'morris-chart-4',data:[{x:'2011 Q1',y:0},{x:'2011 Q2',y:1},{x:'2011 Q3',y:2},{x:'2011 Q4',y:3},{x:'2012 Q1',y:4},{x:'2012 Q2',y:5},{x:'2012 Q3',y:6},{x:'2012 Q4',y:7},{x:'2013 Q1',y:8},{x:'2013 Q2',y:7},{x:'2013 Q3',y:6},{x:'2013 Q4',y:5},{x:'2014 Q1',y:9}],xkey:'x',ykeys:['y'],labels:['Y'],barColors:function(row,series,type){if(type==='bar'){var red=Math.ceil(255*row.y/this.ymax);return 'rgb('+red+',0,0)';}else return '#000';}});}function MorrisChart5(){Morris.Area({element:'morris-chart-5',data:[{period:'2010 Q1',iphone:2666,ipad:null,itouch:2647},{period:'2010 Q2',iphone:2778,ipad:2294,itouch:2441},{period:'2010 Q3',iphone:4912,ipad:1969,itouch:2501},{period:'2010 Q4',iphone:3767,ipad:3597,itouch:5689},{period:'2011 Q1',iphone:6810,ipad:1914,itouch:2293},{period:'2011 Q2',iphone:5670,ipad:4293,itouch:1881},{period:'2011 Q3',iphone:4820,ipad:3795,itouch:1588},{period:'2011 Q4',iphone:15073,ipad:5967,itouch:5175},{period:'2012 Q1',iphone:10687,ipad:4460,itouch:2028},{period:'2012 Q2',iphone:8432,ipad:5713,itouch:1791}],xkey:'period',ykeys:['iphone','ipad','itouch'],labels:['iPhone','iPad','iPod Touch'],pointSize:2,hideHover:'auto'});}function DrawAllCharts(){var chart1_data=[['Smartphones','PC','Notebooks','Monitors','Routers','Switches'],['01.01.2014',1234,2342,344,232,131],['02.01.2014',1254,232,314,232,331],['03.01.2014',2234,342,298,232,665],['04.01.2014',2234,42,559,232,321],['05.01.2014',1999,82,116,232,334],['06.01.2014',1634,834,884,232,191],['07.01.2014',321,342,383,232,556],['08.01.2014',845,112,499,232,731]];var chart1_options={title:'Sales of company',hAxis:{title:'Date',titleTextStyle:{color:'red'}},backgroundColor:'#fcfcfc',vAxis:{title:'Quantity',titleTextStyle:{color:'blue'}}};var chart1_element='google-chart-1';var chart1_type=google.visualization.ColumnChart;drawGoogleChart(chart1_data,chart1_options,chart1_element,chart1_type);var chart2_data=[['Height','Width'],['Samsung',74.5],['Apple',31.24],['LG',12.10],['Huawei',11.14],['Sony',8.3],['Nokia',7.4],['Blackberry',6.8],['HTC',6.63],['Motorola',3.5],['Other',43.15]];var chart2_options={title:'Smartphone marketshare 2Q 2013',backgroundColor:'#fcfcfc'};var chart2_element='google-chart-2';var chart2_type=google.visualization.PieChart;drawGoogleChart(chart2_data,chart2_options,chart2_element,chart2_type);var chart3_data=[['Age','Weight'],[8,12],[4,5.5],[11,14],[4,5],[3,3.5],[6.5,7]];var chart3_options={title:'Age vs. Weight comparison',hAxis:{title:'Age',minValue:0,maxValue:15},vAxis:{title:'Weight',minValue:0,maxValue:15},legend:'none',backgroundColor:'#fcfcfc'};var chart3_element='google-chart-3';var chart3_type=google.visualization.ScatterChart;drawGoogleChart(chart3_data,chart3_options,chart3_element,chart3_type);var chart4_data=[['ID','Life Expectancy','Fertility Rate','Region','Population'],['CAN',80.66,1.67,'North America',33739900],['DEU',79.84,1.36,'Europe',81902307],['DNK',78.6,1.84,'Europe',5523095],['EGY',72.73,2.78,'Middle East',79716203],['GBR',80.05,2,'Europe',61801570],['IRN',72.49,1.7,'Middle East',73137148],['IRQ',68.09,4.77,'Middle East',31090763],['ISR',81.55,2.96,'Middle East',7485600],['RUS',68.6,1.54,'Europe',141850000],['USA',78.09,2.05,'North America',307007000]];var chart4_options={title:'Correlation between life expectancy, fertility rate and population of some world countries (2010)',hAxis:{title:'Life Expectancy'},vAxis:{title:'Fertility Rate'},backgroundColor:'#fcfcfc',bubble:{textStyle:{fontSize:11}}};var chart4_element='google-chart-4';var chart4_type=google.visualization.BubbleChart;drawGoogleChart(chart4_data,chart4_options,chart4_element,chart4_type);var chart5_data=[['Country','Popularity'],['Germany',200],['United States',300],['Brazil',400],['Canada',500],['France',600],['RU',700]];var chart5_options={backgroundColor:'#fcfcfc',enableRegionInteractivity:true};var chart5_element='google-chart-5';var chart5_type=google.visualization.GeoChart;drawGoogleChart(chart5_data,chart5_options,chart5_element,chart5_type);var chart6_data=[['Year','Sales','Expenses'],['2004',1000,400],['2005',1170,460],['2006',660,1120],['2007',1030,540],['2008',2080,740],['2009',1949,690],['2010',2334,820]];var chart6_options={backgroundColor:'#fcfcfc',title:'Company Performance'};var chart6_element='google-chart-6';var chart6_type=google.visualization.LineChart;drawGoogleChart(chart6_data,chart6_options,chart6_element,chart6_type);var chart7_data=[['Task','Hours per Day'],['Work',11],['Eat',2],['Commute',2],['Watch TV',2],['Sleep',7]];var chart7_options={backgroundColor:'#fcfcfc',title:'My Daily Activities',pieHole:0.4};var chart7_element='google-chart-7';var chart7_type=google.visualization.PieChart;drawGoogleChart(chart7_data,chart7_options,chart7_element,chart7_type);var chart8_data=[['Generation','Descendants'],[0,1],[1,33],[2,269],[3,2013]];var chart8_options={backgroundColor:'#fcfcfc',title:'Descendants by Generation',hAxis:{title:'Generation',minValue:0,maxValue:3},vAxis:{title:'Descendants',minValue:0,maxValue:2100},trendlines:{0:{type:'exponential',visibleInLegend:true}}};var chart8_element='google-chart-8';var chart8_type=google.visualization.ScatterChart;drawGoogleChart(chart8_data,chart8_options,chart8_element,chart8_type);}function xGraph1(){var tt=document.createElement('div'),leftOffset=-(~~$('html').css('padding-left').replace('px','')+~~$('body').css('margin-left').replace('px','')),topOffset=-32;tt.className='ex-tooltip';document.body.appendChild(tt);var data={"xScale":"time","yScale":"linear","main":[{"className":".xchart-class-1","data":[{"x":"2012-11-05","y":6},{"x":"2012-11-06","y":6},{"x":"2012-11-07","y":8},{"x":"2012-11-08","y":3},{"x":"2012-11-09","y":4},{"x":"2012-11-10","y":9},{"x":"2012-11-11","y":6},{"x":"2012-11-12","y":16},{"x":"2012-11-13","y":4},{"x":"2012-11-14","y":9},{"x":"2012-11-15","y":2}]}]};var opts={"dataFormatX":function(x){return d3.time.format('%Y-%m-%d').parse(x);},"tickFormatX":function(x){return d3.time.format('%A')(x);},"mouseover":function(d,i){var pos=$(this).offset();$(tt).text(d3.time.format('%A')(d.x)+': '+d.y).css({top:topOffset+pos.top,left:pos.left+leftOffset}).show();},"mouseout":function(x){$(tt).hide();}};var myChart=new xChart('line-dotted',data,'#xchart-1',opts);}function xGraph2(){var data={"xScale":"ordinal","yScale":"linear","main":[{"className":".xchart-class-2","data":[{"x":"Apple","y":575},{"x":"Facebook","y":163},{"x":"Microsoft","y":303},{"x":"Cisco","y":121},{"x":"Google","y":393}]}]};var myChart=new xChart('bar',data,'#xchart-2');}function xGraph3(){var data={"xScale":"time","yScale":"linear","type":"line","main":[{"className":".xchart-class-3","data":[{"x":"2012-11-05","y":1},{"x":"2012-11-06","y":6},{"x":"2012-11-07","y":13},{"x":"2012-11-08","y":-3},{"x":"2012-11-09","y":-4},{"x":"2012-11-10","y":9},{"x":"2012-11-11","y":6},{"x":"2012-11-12","y":7},{"x":"2012-11-13","y":-2},{"x":"2012-11-14","y":-7}]}]};var opts={"dataFormatX":function(x){return d3.time.format('%Y-%m-%d').parse(x);},"tickFormatX":function(x){return d3.time.format('%A')(x);}};var myChart=new xChart('line',data,'#xchart-3',opts);}function CoinDeskGraph(){var dates=PrettyDates();var startdate=dates[0];var enddate=dates[1];var jsonURL='http://api.coindesk.com/v1/bpi/historical/close.json?start='+startdate+'&end='+enddate;$.getJSON(jsonURL,function(result){$.each(result.bpi,function(key,val){xchart_data.push({'x':key,'y':val});});var graphXChartResize;$('#coindesk-xchart').resize(function(){clearTimeout(graphXChartResize);graphXChartResize=setTimeout(DrawCoinDeskXCharts,500);});DrawCoinDeskXCharts();$.each(result.bpi,function(key,val){google_data.push([key,val]);});var graphGChartResize;$('#coindesk-google-chart').resize(function(){clearTimeout(graphGChartResize);graphGChartResize=setTimeout(DrawCoinDeskGoogleCharts,500);});DrawCoinDeskGoogleCharts();$.each(result.bpi,function(key,val){var parseDate=key;parseDate=parseDate.split("-");var newDate=parseDate[1]+"/"+parseDate[2]+"/"+parseDate[0];var new_date=new Date(newDate).getTime();exchange_rate.push([new_date,val]);});DrawCoinDeskFlot();var graphSparklineResize;$('#coindesk-sparklines').resize(function(){clearTimeout(graphSparklineResize);graphSparklineResize=setTimeout(DrawCoinDeskSparkLine,500);});DrawCoinDeskSparkLine();});}function DrawCoinDeskSparkLine(){$('#coindesk-sparklines').sparkline(exchange_rate,{height:'100%',width:'100%'});}function DrawCoinDeskXCharts(){var data={"xScale":"ordinal","yScale":"linear","main":[{"className":".pizza","data":xchart_data}]};var myChart=new xChart('line-dotted',data,'#coindesk-xchart');}function DrawCoinDeskFlot(){var data1=[{data:exchange_rate,label:"Bitcoin exchange rate ($)"}];var options={canvas:true,xaxes:[{mode:"time"}],yaxes:[{min:0},{position:"right",alignTicksWithAxis:1,tickFormatter:function(value,axis){return value.toFixed(axis.tickDecimals)+"€";}}],legend:{position:"sw"}};$.plot("#coindesk-flot",data1,options);}function DrawCoinDeskGoogleCharts(){var google_options={backgroundColor:'#fcfcfc',title:'Coindesk Exchange Rate'};var google_element='coindesk-google-chart';var google_type=google.visualization.LineChart;drawGoogleChart(google_data,google_options,google_element,google_type);}function TestTable1(){$('#datatable-1').dataTable({"aaSorting":[[0,"asc"]],"sDom":"<'box-content'<'col-sm-6'f><'col-sm-6 text-right'l><'clearfix'>>rt<'box-content'<'col-sm-6'i><'col-sm-6 text-right'p><'clearfix'>>","sPaginationType":"bootstrap","oLanguage":{"sSearch":"","sLengthMenu":'_MENU_'}});}function TestTable2(){var asInitVals=[];var oTable=$('#datatable-2').dataTable({"aaSorting":[[0,"asc"]],"sDom":"<'box-content'<'col-sm-6'f><'col-sm-6 text-right'l><'clearfix'>>rt<'box-content'<'col-sm-6'i><'col-sm-6 text-right'p><'clearfix'>>","sPaginationType":"bootstrap","oLanguage":{"sSearch":"","sLengthMenu":'_MENU_'},bAutoWidth:false});var header_inputs=$("#datatable-2 thead input");header_inputs.on('keyup',function(){oTable.fnFilter(this.value,header_inputs.index(this));}).on('focus',function(){if(this.className=="search_init"){this.className="";this.value="";}}).on('blur',function(i){if(this.value==""){this.className="search_init";this.value=asInitVals[header_inputs.index(this)];}});header_inputs.each(function(i){asInitVals[i]=this.value;});}function TestTable3(){$('#datatable-3').dataTable({"aaSorting":[[0,"asc"]],"sDom":"T<'box-content'<'col-sm-6'f><'col-sm-6 text-right'l><'clearfix'>>rt<'box-content'<'col-sm-6'i><'col-sm-6 text-right'p><'clearfix'>>","sPaginationType":"bootstrap","oLanguage":{"sSearch":"","sLengthMenu":'_MENU_'},"oTableTools":{"sSwfPath":"plugins/datatables/copy_csv_xls_pdf.swf","aButtons":["copy","print",{"sExtends":"collection","sButtonText":'Save ',"aButtons":["csv","xls","pdf"]}]}});}function SmallChangeVal(val){var new_val=Math.floor(100*Math.random());var plusOrMinus=Math.random()<0.5?-1:1;var result=val[0]+new_val*plusOrMinus;if(parseInt(result)>1000)return [val[0]-new_val];if(parseInt(result)<0)return [val[0]+new_val];return [result];}function SparklineTestData(){var arr=[];for(var i=1;i<9;i++)arr.push([Math.floor(1000*Math.random())]);return arr;}function RedrawKnob(elem){elem.animate({value:Math.floor(100*Math.random())},{duration:3000,easing:'swing',progress:function(){$(this).val(parseInt(Math.ceil(elem.val()))).trigger('change');}});}function SparklineLoop(){SparkLineDrawBarGraph($('#sparkline-1'),sparkline_arr_1.map(SmallChangeVal));SparkLineDrawBarGraph($('#sparkline-2'),sparkline_arr_2.map(SmallChangeVal),'#7BC5D3');SparkLineDrawBarGraph($('#sparkline-3'),sparkline_arr_3.map(SmallChangeVal),'#B25050');}function MorrisDashboard(){Morris.Line({element:'stat-graph',data:[{"period":"2014-01","Win8":13.4,"Win7":55.3,'Vista':1.5,'NT':0.3,'XP':11,'Linux':4.9,'Mac':9.6,'Mobile':4},{"period":"2013-12","Win8":10,"Win7":55.9,'Vista':1.5,'NT':3.1,'XP':11.6,'Linux':4.8,'Mac':9.2,'Mobile':3.8},{"period":"2013-11","Win8":8.6,"Win7":56.4,'Vista':1.6,'NT':3.7,'XP':11.7,'Linux':4.8,'Mac':9.6,'Mobile':3.7},{"period":"2013-10","Win8":9.9,"Win7":56.7,'Vista':1.6,'NT':1.4,'XP':12.4,'Linux':4.9,'Mac':9.6,'Mobile':3.3},{"period":"2013-09","Win8":10.2,"Win7":56.8,'Vista':1.6,'NT':0.4,'XP':13.5,'Linux':4.8,'Mac':9.3,'Mobile':3.3},{"period":"2013-08","Win8":9.6,"Win7":55.9,'Vista':1.7,'NT':0.4,'XP':14.7,'Linux':5,'Mac':9.2,'Mobile':3.4},{"period":"2013-07","Win8":9,"Win7":56.2,'Vista':1.8,'NT':0.4,'XP':15.8,'Linux':4.9,'Mac':8.7,'Mobile':3.2},{"period":"2013-06","Win8":8.6,"Win7":56.3,'Vista':2,'NT':0.4,'XP':15.4,'Linux':4.9,'Mac':9.1,'Mobile':3.2},{"period":"2013-05","Win8":7.9,"Win7":56.4,'Vista':2.1,'NT':0.4,'XP':15.7,'Linux':4.9,'Mac':9.7,'Mobile':2.6},{"period":"2013-04","Win8":7.3,"Win7":56.4,'Vista':2.2,'NT':0.4,'XP':16.4,'Linux':4.8,'Mac':9.7,'Mobile':2.2},{"period":"2013-03","Win8":6.7,"Win7":55.9,'Vista':2.4,'NT':0.4,'XP':17.6,'Linux':4.7,'Mac':9.5,'Mobile':2.3},{"period":"2013-02","Win8":5.7,"Win7":55.3,'Vista':2.4,'NT':0.4,'XP':19.1,'Linux':4.8,'Mac':9.6,'Mobile':2.2},{"period":"2013-01","Win8":4.8,"Win7":55.3,'Vista':2.6,'NT':0.5,'XP':19.9,'Linux':4.8,'Mac':9.3,'Mobile':2.2}],xkey:'period',ykeys:['Win8','Win7','Vista','NT','XP','Linux','Mac','Mobile'],labels:['Win8','Win7','Vista','NT','XP','Linux','Mac','Mobile']});Morris.Donut({element:'morris_donut_1',data:[{value:70,label:'pay',formatted:'at least 70%'},{value:15,label:'client',formatted:'approx. 15%'},{value:10,label:'buy',formatted:'approx. 10%'},{value:5,label:'hosted',formatted:'at most 5%'}],formatter:function(x,data){return data.formatted;}});Morris.Donut({element:'morris_donut_2',data:[{value:20,label:'office',formatted:'current'},{value:35,label:'store',formatted:'approx. 35%'},{value:20,label:'shop',formatted:'approx. 20%'},{value:25,label:'cars',formatted:'at most 25%'}],formatter:function(x,data){return data.formatted;}});Morris.Donut({element:'morris_donut_3',data:[{value:17,label:'current',formatted:'current'},{value:22,label:'week',formatted:'last week'},{value:10,label:'month',formatted:'last month'},{value:25,label:'period',formatted:'period'},{value:25,label:'year',formatted:'this year'}],formatter:function(x,data){return data.formatted;}});}function DrawSparklineDashboard(){SparklineLoop();setInterval(SparklineLoop,1000);var sparkline_clients=[[309],[223],[343],[652],[455],[18],[912],[15]];$('.bar').each(function(){$(this).sparkline(sparkline_clients.map(SmallChangeVal),{type:'bar',barWidth:5,highlightColor:'#000',barSpacing:2,height:30,stackedBarColor:'#6AA6D6'});});var sparkline_table=[[1,341],[2,464],[4,564],[5,235],[6,335],[7,535],[8,642],[9,342],[10,765]];$('.td-graph').each(function(){var arr=$.map(sparkline_table,function(val,index){return [[val[0],SmallChangeVal([val[1]])]];});$(this).sparkline(arr,{defaultPixelsPerValue:10,minSpotColor:null,maxSpotColor:null,spotColor:null,fillColor:false,lineWidth:2,lineColor:'#5A8DB6'});});}function DrawKnobDashboard(){var srv_monitoring_selectors=[$("#knob-srv-1"),$("#knob-srv-2"),$("#knob-srv-3"),$("#knob-srv-4"),$("#knob-srv-5"),$("#knob-srv-6")];srv_monitoring_selectors.forEach(DrawKnob);setInterval(function(){srv_monitoring_selectors.forEach(RedrawKnob);},3000);}function FileUpload(){$('#bootstrapped-fine-uploader').fineUploader({template:'qq-template-bootstrap',classes:{success:'alert alert-success',fail:'alert alert-error'},thumbnails:{placeholders:{waitingPath:"assets/waiting-generic.png",notAvailablePath:"assets/not_available-generic.png"}},request:{endpoint:'server/handleUploads'},validation:{allowedExtensions:['jpeg','jpg','gif','png']}});}function LoadTestMap(){$.getJSON("http://www.telize.com/geoip?callback=?",function(json){var osmap=new OpenLayers.Layer.OSM("OpenStreetMap");var googlestreets=new OpenLayers.Layer.Google("Google Streets",{numZoomLevels:22,visibility:false});var googlesattelite=new OpenLayers.Layer.Google("Google Sattelite",{type:google.maps.MapTypeId.SATELLITE,numZoomLevels:22});var map1_layers=[googlestreets,osmap,googlesattelite];var map1=drawMap(json.longitude,json.latitude,"map-1",map1_layers);$("#map-1").resize(function(){setTimeout(map1.updateSize(),500);});var osmap1=new OpenLayers.Layer.OSM("OpenStreetMap");var map2_layers=[osmap1];var map2=drawMap(json.longitude,json.latitude,"map-2",map2_layers);$("#map-2").resize(function(){setTimeout(map2.updateSize(),500);});var sattelite=new OpenLayers.Layer.Google("Google Sattelite",{type:google.maps.MapTypeId.SATELLITE,numZoomLevels:22});var map3_layers=[sattelite];var map3=drawMap(json.longitude,json.latitude,"map-3",map3_layers);$("#map-3").resize(function(){setTimeout(map3.updateSize(),500);});});}function FullScreenMap(){$.getJSON("http://www.telize.com/geoip?callback=?",function(json){var osmap=new OpenLayers.Layer.OSM("OpenStreetMap");var googlestreets=new OpenLayers.Layer.Google("Google Streets",{numZoomLevels:22,visibility:false});var googlesattelite=new OpenLayers.Layer.Google("Google Sattelite",{type:google.maps.MapTypeId.SATELLITE,numZoomLevels:22});var map1_layers=[googlestreets,osmap,googlesattelite];var map_fs=drawMap(json.longitude,json.latitude,"full-map",map1_layers);});}function displayFlickrImages(data){var res;$.each(data.items,function(i,item){if(i>11)return false;res="+item.title+";$('#box-one-content').append(res);});setTimeout(function(){$("#box-one-content").justifiedGallery({'usedSuffix':'lt240','justifyLastRow':true,'rowHeight':150,'fixedHeight':false,'captions':true,'margins':1});$('#box-one-content').fadeIn('slow');},100);}function DemoFormValidator(){$('#defaultForm').bootstrapValidator({message:'This value is not valid',fields:{username:{message:'The username is not valid',validators:{notEmpty:{message:'The username is required and can\'t be empty'},stringLength:{min:6,max:30,message:'The username must be more than 6 and less than 30 characters long'},regexp:{regexp:/^[a-zA-Z0-9_\.]+$/,message:'The username can only consist of alphabetical, number, dot and underscore'}}},country:{validators:{notEmpty:{message:'The country is required and can\'t be empty'}}},acceptTerms:{validators:{notEmpty:{message:'You have to accept the terms and policies'}}},email:{validators:{notEmpty:{message:'The email address is required and can\'t be empty'},emailAddress:{message:'The input is not a valid email address'}}},website:{validators:{uri:{message:'The input is not a valid URL'}}},phoneNumber:{validators:{digits:{message:'The value can contain only digits'}}},color:{validators:{hexColor:{message:'The input is not a valid hex color'}}},zipCode:{validators:{usZipCode:{message:'The input is not a valid US zip code'}}},password:{validators:{notEmpty:{message:'The password is required and can\'t be empty'},identical:{field:'confirmPassword',message:'The password and its confirm are not the same'}}},confirmPassword:{validators:{notEmpty:{message:'The confirm password is required and can\'t be empty'},identical:{field:'password',message:'The password and its confirm are not the same'}}},ages:{validators:{lessThan:{value:100,inclusive:true,message:'The ages has to be less than 100'},greaterThan:{value:10,inclusive:false,message:'The ages has to be greater than or equals to 10'}}}}});}function FormLayoutExampleInputLength(selector){var steps=["col-sm-1","col-sm-2","col-sm-3","col-sm-4","col-sm-5","col-sm-6","col-sm-7","col-sm-8","col-sm-9","col-sm-10","col-sm-11","col-sm-12"];selector.slider({range:'min',value:1,min:0,max:11,step:1,slide:function(event,ui){if(ui.value<1)return false;var input=$("#form-styles");var f=input.parent();f.removeClass();f.addClass(steps[ui.value]);input.attr("placeholder",'.'+steps[ui.value]);}});}function RunClock(){var second=$(".second");var minute=$(".minute");var hour=$(".hour");var d=new Date();var s=d.getSeconds();var m=d.getMinutes();var h=d.getHours();if(h>11)h=h-12;$('#knob-clock-value').html(h+':'+m+':'+s);second.val(s).trigger("change");minute.val(m).trigger("change");hour.val(h).trigger("change");}function CreateAllSliders(){$(".slider-default").slider();var slider_range_min_amount=$(".slider-range-min-amount");var slider_range_min=$(".slider-range-min");var slider_range_max=$(".slider-range-max");var slider_range_max_amount=$(".slider-range-max-amount");var slider_range=$(".slider-range");var slider_range_amount=$(".slider-range-amount");slider_range_min.slider({range:"min",value:37,min:1,max:700,slide:function(event,ui){slider_range_min_amount.val("$"+ui.value);}});slider_range_min_amount.val("$"+slider_range_min.slider("value"));slider_range_max.slider({range:"max",min:1,max:100,value:2,slide:function(event,ui){slider_range_max_amount.val(ui.value);}});slider_range_max_amount.val(slider_range_max.slider("value"));slider_range.slider({range:true,min:0,max:500,values:[75,300],slide:function(event,ui){slider_range_amount.val("$"+ui.values[0]+" - $"+ui.values[1]);}});slider_range_amount.val("$"+slider_range.slider("values",0)+" - $"+slider_range.slider("values",1));$("#equalizer > div.progress > div").each(function(){var value=parseInt($(this).text(),10);$(this).empty().slider({value:value,range:"min",animate:true,orientation:"vertical"});});}function AllTimePickers(){$('#datetime_example').datetimepicker({});$('#time_example').timepicker({hourGrid:4,minuteGrid:10,timeFormat:'hh:mm tt'});$('#date3_example').datepicker({numberOfMonths:3,showButtonPanel:true});$('#date3-1_example').datepicker({numberOfMonths:3,showButtonPanel:true});$('#date_example').datepicker({});}function DrawCalendar(){$('#external-events div.external-event').each(function(){var eventObject={title:$.trim($(this).text())};$(this).data('eventObject',eventObject);$(this).draggable({zIndex:999,revert:true,revertDuration:0});});var calendar=$('#calendar').fullCalendar({header:{left:'prev,next today',center:'title',right:'month,agendaWeek,agendaDay'},selectable:true,selectHelper:true,select:function(start,end,allDay){var form=$('
'+'
'+'Event name'+'
'+''+'
'+''+'
'+''+'
'+'
'+'
');var buttons=$(''+'');OpenModalBox('Add event',form,buttons);$('#event_cancel').on('click',function(){CloseModalBox();});$('#event_submit').on('click',function(){var new_event_name=$('#newevent_name').val();if(new_event_name!='')calendar.fullCalendar('renderEvent',{title:new_event_name,description:$('#newevent_desc').val(),start:start,end:end,allDay:allDay},true);CloseModalBox();});calendar.fullCalendar('unselect');},editable:true,droppable:true,drop:function(date,allDay){var originalEventObject=$(this).data('eventObject');var copiedEventObject=$.extend({},originalEventObject);copiedEventObject.start=date;copiedEventObject.allDay=allDay;$('#calendar').fullCalendar('renderEvent',copiedEventObject,true);if($('#drop-remove').is(':checked'))$(this).remove();},eventRender:function(event,element,icon){if(event.description!="")element.attr('title',event.description);},eventClick:function(calEvent,jsEvent,view){var form=$('
'+'
'+'Event name'+'
'+''+'
'+''+'
'+''+'
'+'
'+'
');var buttons=$(''+''+'');OpenModalBox('Change event',form,buttons);$('#event_cancel').on('click',function(){CloseModalBox();});$('#event_delete').on('click',function(){calendar.fullCalendar('removeEvents',function(ev){return(ev._id==calEvent._id);});CloseModalBox();});$('#event_change').on('click',function(){calEvent.title=$('#newevent_name').val();calEvent.description=$('#newevent_desc').val();calendar.fullCalendar('updateEvent',calEvent);CloseModalBox();});}});$('#new-event-add').on('click',function(event){event.preventDefault();var event_name=$('#new-event-title').val();var event_description=$('#new-event-desc').val();if(event_name!=''){var event_template=$('
'+event_name+'
');$('#events-templates-header').after(event_template);var eventObject={title:event_name,description:event_description};event_template.data('eventObject',eventObject);event_template.draggable({zIndex:999,revert:true,revertDuration:0});}});}function DrawFullCalendar(){LoadCalendarScript(DrawCalendar);}$(document).ready(function(){$('.show-sidebar').on('click',function(){$('div#main').toggleClass('sidebar-show');setTimeout(MessagesMenuWidth,250);});var ajax_url=location.hash.replace(/^#/,'');if(ajax_url.length<1)ajax_url='ajax/dashboard.html';LoadAjaxContent(ajax_url);$('.main-menu').on('click','a',function(e){var parents=$(this).parents('li');var li=$(this).closest('li.dropdown');var another_items=$('.main-menu li').not(parents);another_items.find('a').removeClass('active');another_items.find('a').removeClass('active-parent');if($(this).hasClass('dropdown-toggle')||$(this).closest('li').find('ul').length==0){$(this).addClass('active-parent');var current=$(this).next();if(current.is(':visible')){li.find("ul.dropdown-menu").slideUp('fast');li.find("ul.dropdown-menu a").removeClass('active');}else{another_items.find("ul.dropdown-menu").slideUp('fast');current.slideDown('fast');}}else if(li.find('a.dropdown-toggle').hasClass('active-parent')){var pre=$(this).closest('ul.dropdown-menu');pre.find("li.dropdown").not($(this).closest('li')).find('ul.dropdown-menu').slideUp('fast');}if($(this).hasClass('active')==false){$(this).parents("ul.dropdown-menu").find('a').removeClass('active');$(this).addClass('active');}if($(this).hasClass('ajax-link')){e.preventDefault();if($(this).hasClass('add-full'))$('#content').addClass('full-content');else $('#content').removeClass('full-content');var url=$(this).attr('href');window.location.hash=url;LoadAjaxContent(url);}if($(this).attr('href')=='#')e.preventDefault();});var height=window.innerHeight-49;$('#main').css('min-height',height).on('click','.expand-link',function(e){var body=$('body');e.preventDefault();var box=$(this).closest('div.box');var button=$(this).find('i');button.toggleClass('fa-expand').toggleClass('fa-compress');box.toggleClass('expanded');body.toggleClass('body-expanded');var timeout=0;if(body.hasClass('body-expanded'))timeout=100;setTimeout(function(){box.toggleClass('expanded-padding');},timeout);setTimeout(function(){box.resize();box.find('[id^=map-]').resize();},timeout+50);}).on('click','.collapse-link',function(e){e.preventDefault();var box=$(this).closest('div.box');var button=$(this).find('i');var content=box.find('div.box-content');content.slideToggle('fast');button.toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');setTimeout(function(){box.resize();box.find('[id^=map-]').resize();},50);}).on('click','.close-link',function(e){e.preventDefault();var content=$(this).closest('div.box');content.remove();});$('#locked-screen').on('click',function(e){e.preventDefault();$('body').addClass('body-screensaver');$('#screensaver').addClass("show");ScreenSaver();});$('body').on('click','a.close-link',function(e){e.preventDefault();CloseModalBox();});$('#top-panel').on('click','a',function(e){if($(this).hasClass('ajax-link')){e.preventDefault();if($(this).hasClass('add-full'))$('#content').addClass('full-content');else $('#content').removeClass('full-content');var url=$(this).attr('href');window.location.hash=url;LoadAjaxContent(url);}});$('#search').on('keydown',function(e){if(e.keyCode==13){e.preventDefault();$('#content').removeClass('full-content');ajax_url='ajax/page_search.html';window.location.hash=ajax_url;LoadAjaxContent(ajax_url);}});$('#screen_unlock').on('mouseover',function(){var header='Enter current username and password';var form=$('
'+'
');var button=$('');OpenModalBox(header,form,button);});}); \ No newline at end of file diff --git a/plugins/web_gui/static/js/noty/jquery.noty.js b/plugins/web_gui/static/js/noty/jquery.noty.js new file mode 100644 index 0000000..6d1e202 --- /dev/null +++ b/plugins/web_gui/static/js/noty/jquery.noty.js @@ -0,0 +1,488 @@ +/** + * noty - jQuery Notification Plugin v2.2.2 + * Contributors: https://github.com/needim/noty/graphs/contributors + * + * Examples and Documentation - http://needim.github.com/noty/ + * + * Licensed under the MIT licenses: + * http://www.opensource.org/licenses/mit-license.php + * + **/ + +if (typeof Object.create !== 'function') { + Object.create = function (o) { + function F() { + } + + F.prototype = o; + return new F(); + }; +} + +(function ($) { + + var NotyObject = { + + init:function (options) { + + // Mix in the passed in options with the default options + this.options = $.extend({}, $.noty.defaults, options); + + this.options.layout = (this.options.custom) ? $.noty.layouts['inline'] : $.noty.layouts[this.options.layout]; + + if ($.noty.themes[this.options.theme]) + this.options.theme = $.noty.themes[this.options.theme]; + else + options.themeClassName = this.options.theme; + + delete options.layout; + delete options.theme; + + this.options = $.extend({}, this.options, this.options.layout.options); + this.options.id = 'noty_' + (new Date().getTime() * Math.floor(Math.random() * 1000000)); + + this.options = $.extend({}, this.options, options); + + // Build the noty dom initial structure + this._build(); + + // return this so we can chain/use the bridge with less code. + return this; + }, // end init + + _build:function () { + + // Generating noty bar + var $bar = $('
').attr('id', this.options.id); + $bar.append(this.options.template).find('.noty_text').html(this.options.text); + + this.$bar = (this.options.layout.parent.object !== null) ? $(this.options.layout.parent.object).css(this.options.layout.parent.css).append($bar) : $bar; + + if (this.options.themeClassName) + this.$bar.addClass(this.options.themeClassName).addClass('noty_container_type_' + this.options.type); + + // Set buttons if available + if (this.options.buttons) { + + // If we have button disable closeWith & timeout options + this.options.closeWith = []; + this.options.timeout = false; + + var $buttons = $('
').addClass('noty_buttons'); + + (this.options.layout.parent.object !== null) ? this.$bar.find('.noty_bar').append($buttons) : this.$bar.append($buttons); + + var self = this; + + $.each(this.options.buttons, function (i, button) { + var $button = $('
'+ + '

Copied '+len+' row'+plural+' to the clipboard.

', + 1500 + ); + } + } ), + + "pdf": $.extend( {}, TableTools.buttonBase, { + "sAction": "flash_pdf", + "sNewLine": "\n", + "sFileName": "*.pdf", + "sButtonClass": "DTTT_button_pdf", + "sButtonText": "PDF", + "sPdfOrientation": "portrait", + "sPdfSize": "A4", + "sPdfMessage": "", + "fnClick": function( nButton, oConfig, flash ) { + this.fnSetText( flash, + "title:"+ this.fnGetTitle(oConfig) +"\n"+ + "message:"+ oConfig.sPdfMessage +"\n"+ + "colWidth:"+ this.fnCalcColRatios(oConfig) +"\n"+ + "orientation:"+ oConfig.sPdfOrientation +"\n"+ + "size:"+ oConfig.sPdfSize +"\n"+ + "--/TableToolsOpts--\n" + + this.fnGetTableData(oConfig) + ); + } + } ), + + "print": $.extend( {}, TableTools.buttonBase, { + "sInfo": "
Print view

Please use your browser's print function to "+ + "print this table. Press escape when finished.", + "sMessage": null, + "bShowAll": true, + "sToolTip": "View print view", + "sButtonClass": "DTTT_button_print", + "sButtonText": "Print", + "fnClick": function ( nButton, oConfig ) { + this.fnPrint( true, oConfig ); + } + } ), + + "text": $.extend( {}, TableTools.buttonBase ), + + "select": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Select button", + "fnSelect": function( nButton, oConfig ) { + if ( this.fnGetSelected().length !== 0 ) { + $(nButton).removeClass( this.classes.buttons.disabled ); + } else { + $(nButton).addClass( this.classes.buttons.disabled ); + } + }, + "fnInit": function( nButton, oConfig ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } + } ), + + "select_single": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Select button", + "fnSelect": function( nButton, oConfig ) { + var iSelected = this.fnGetSelected().length; + if ( iSelected == 1 ) { + $(nButton).removeClass( this.classes.buttons.disabled ); + } else { + $(nButton).addClass( this.classes.buttons.disabled ); + } + }, + "fnInit": function( nButton, oConfig ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } + } ), + + "select_all": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Select all", + "fnClick": function( nButton, oConfig ) { + this.fnSelectAll(); + }, + "fnSelect": function( nButton, oConfig ) { + if ( this.fnGetSelected().length == this.s.dt.fnRecordsDisplay() ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } else { + $(nButton).removeClass( this.classes.buttons.disabled ); + } + } + } ), + + "select_none": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Deselect all", + "fnClick": function( nButton, oConfig ) { + this.fnSelectNone(); + }, + "fnSelect": function( nButton, oConfig ) { + if ( this.fnGetSelected().length !== 0 ) { + $(nButton).removeClass( this.classes.buttons.disabled ); + } else { + $(nButton).addClass( this.classes.buttons.disabled ); + } + }, + "fnInit": function( nButton, oConfig ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } + } ), + + "ajax": $.extend( {}, TableTools.buttonBase, { + "sAjaxUrl": "/xhr.php", + "sButtonText": "Ajax button", + "fnClick": function( nButton, oConfig ) { + var sData = this.fnGetTableData(oConfig); + $.ajax( { + "url": oConfig.sAjaxUrl, + "data": [ + { "name": "tableData", "value": sData } + ], + "success": oConfig.fnAjaxComplete, + "dataType": "json", + "type": "POST", + "cache": false, + "error": function () { + alert( "Error detected when sending table data to server" ); + } + } ); + }, + "fnAjaxComplete": function( json ) { + alert( 'Ajax complete' ); + } + } ), + + "div": $.extend( {}, TableTools.buttonBase, { + "sAction": "div", + "sTag": "div", + "sButtonClass": "DTTT_nonbutton", + "sButtonText": "Text button" + } ), + + "collection": $.extend( {}, TableTools.buttonBase, { + "sAction": "collection", + "sButtonClass": "DTTT_button_collection", + "sButtonText": "Collection", + "fnClick": function( nButton, oConfig ) { + this._fnCollectionShow(nButton, oConfig); + } + } ) +}; +/* + * on* callback parameters: + * 1. node - button element + * 2. object - configuration object for this button + * 3. object - ZeroClipboard reference (flash button only) + * 4. string - Returned string from Flash (flash button only - and only on 'complete') + */ + + + +/** + * @namespace Classes used by TableTools - allows the styles to be override easily. + * Note that when TableTools initialises it will take a copy of the classes object + * and will use its internal copy for the remainder of its run time. + */ +TableTools.classes = { + "container": "DTTT_container", + "buttons": { + "normal": "DTTT_button", + "disabled": "DTTT_disabled" + }, + "collection": { + "container": "DTTT_collection", + "background": "DTTT_collection_background", + "buttons": { + "normal": "DTTT_button", + "disabled": "DTTT_disabled" + } + }, + "select": { + "table": "DTTT_selectable", + "row": "DTTT_selected" + }, + "print": { + "body": "DTTT_Print", + "info": "DTTT_print_info", + "message": "DTTT_PrintMessage" + } +}; + + +/** + * @namespace ThemeRoller classes - built in for compatibility with DataTables' + * bJQueryUI option. + */ +TableTools.classes_themeroller = { + "container": "DTTT_container ui-buttonset ui-buttonset-multi", + "buttons": { + "normal": "DTTT_button ui-button ui-state-default" + }, + "collection": { + "container": "DTTT_collection ui-buttonset ui-buttonset-multi" + } +}; + + +/** + * @namespace TableTools default settings for initialisation + */ +TableTools.DEFAULTS = { + "sSwfPath": "media/swf/copy_csv_xls_pdf.swf", + "sRowSelect": "none", + "sSelectedClass": null, + "fnPreRowSelect": null, + "fnRowSelected": null, + "fnRowDeselected": null, + "aButtons": [ "copy", "csv", "xls", "pdf", "print" ], + "oTags": { + "container": "div", + "button": "a", // We really want to use buttons here, but Firefox and IE ignore the + // click on the Flash element in the button (but not mouse[in|out]). + "liner": "span", + "collection": { + "container": "div", + "button": "a", + "liner": "span" + } + } +}; + + +/** + * Name of this class + * @constant CLASS + * @type String + * @default TableTools + */ +TableTools.prototype.CLASS = "TableTools"; + + +/** + * TableTools version + * @constant VERSION + * @type String + * @default See code + */ +TableTools.VERSION = "2.1.4"; +TableTools.prototype.VERSION = TableTools.VERSION; + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Initialisation + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Register a new feature with DataTables + */ +if ( typeof $.fn.dataTable == "function" && + typeof $.fn.dataTableExt.fnVersionCheck == "function" && + $.fn.dataTableExt.fnVersionCheck('1.9.0') ) +{ + $.fn.dataTableExt.aoFeatures.push( { + "fnInit": function( oDTSettings ) { + var oOpts = typeof oDTSettings.oInit.oTableTools != 'undefined' ? + oDTSettings.oInit.oTableTools : {}; + + var oTT = new TableTools( oDTSettings.oInstance, oOpts ); + TableTools._aInstances.push( oTT ); + + return oTT.dom.container; + }, + "cFeature": "T", + "sFeature": "TableTools" + } ); +} +else +{ + alert( "Warning: TableTools 2 requires DataTables 1.9.0 or newer - www.datatables.net/download"); +} + +$.fn.DataTable.TableTools = TableTools; + +})(jQuery, window, document); diff --git a/plugins/web_gui/static/plugins/datatables/TableTools_orig.js b/plugins/web_gui/static/plugins/datatables/TableTools_orig.js new file mode 100644 index 0000000..9e0cb00 --- /dev/null +++ b/plugins/web_gui/static/plugins/datatables/TableTools_orig.js @@ -0,0 +1,2475 @@ +/* + * File: TableTools.js + * Version: 2.1.4 + * Description: Tools and buttons for DataTables + * Author: Allan Jardine (www.sprymedia.co.uk) + * Language: Javascript + * License: GPL v2 or BSD 3 point style + * Project: DataTables + * + * Copyright 2009-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + */ + +/* Global scope for TableTools */ +var TableTools; + +(function($, window, document) { + +/** + * TableTools provides flexible buttons and other tools for a DataTables enhanced table + * @class TableTools + * @constructor + * @param {Object} oDT DataTables instance + * @param {Object} oOpts TableTools options + * @param {String} oOpts.sSwfPath ZeroClipboard SWF path + * @param {String} oOpts.sRowSelect Row selection options - 'none', 'single' or 'multi' + * @param {Function} oOpts.fnPreRowSelect Callback function just prior to row selection + * @param {Function} oOpts.fnRowSelected Callback function just after row selection + * @param {Function} oOpts.fnRowDeselected Callback function when row is deselected + * @param {Array} oOpts.aButtons List of buttons to be used + */ +TableTools = function( oDT, oOpts ) +{ + /* Santiy check that we are a new instance */ + if ( ! this instanceof TableTools ) + { + alert( "Warning: TableTools must be initialised with the keyword 'new'" ); + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class variables + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * @namespace Settings object which contains customisable information for TableTools instance + */ + this.s = { + /** + * Store 'this' so the instance can be retrieved from the settings object + * @property that + * @type object + * @default this + */ + "that": this, + + /** + * DataTables settings objects + * @property dt + * @type object + * @default From the oDT init option + */ + "dt": oDT.fnSettings(), + + /** + * @namespace Print specific information + */ + "print": { + /** + * DataTables draw 'start' point before the printing display was shown + * @property saveStart + * @type int + * @default -1 + */ + "saveStart": -1, + + /** + * DataTables draw 'length' point before the printing display was shown + * @property saveLength + * @type int + * @default -1 + */ + "saveLength": -1, + + /** + * Page scrolling point before the printing display was shown so it can be restored + * @property saveScroll + * @type int + * @default -1 + */ + "saveScroll": -1, + + /** + * Wrapped function to end the print display (to maintain scope) + * @property funcEnd + * @type Function + * @default function () {} + */ + "funcEnd": function () {} + }, + + /** + * A unique ID is assigned to each button in each instance + * @property buttonCounter + * @type int + * @default 0 + */ + "buttonCounter": 0, + + /** + * @namespace Select rows specific information + */ + "select": { + /** + * Select type - can be 'none', 'single' or 'multi' + * @property type + * @type string + * @default "" + */ + "type": "", + + /** + * Array of nodes which are currently selected + * @property selected + * @type array + * @default [] + */ + "selected": [], + + /** + * Function to run before the selection can take place. Will cancel the select if the + * function returns false + * @property preRowSelect + * @type Function + * @default null + */ + "preRowSelect": null, + + /** + * Function to run when a row is selected + * @property postSelected + * @type Function + * @default null + */ + "postSelected": null, + + /** + * Function to run when a row is deselected + * @property postDeselected + * @type Function + * @default null + */ + "postDeselected": null, + + /** + * Indicate if all rows are selected (needed for server-side processing) + * @property all + * @type boolean + * @default false + */ + "all": false, + + /** + * Class name to add to selected TR nodes + * @property selectedClass + * @type String + * @default "" + */ + "selectedClass": "" + }, + + /** + * Store of the user input customisation object + * @property custom + * @type object + * @default {} + */ + "custom": {}, + + /** + * SWF movie path + * @property swfPath + * @type string + * @default "" + */ + "swfPath": "", + + /** + * Default button set + * @property buttonSet + * @type array + * @default [] + */ + "buttonSet": [], + + /** + * When there is more than one TableTools instance for a DataTable, there must be a + * master which controls events (row selection etc) + * @property master + * @type boolean + * @default false + */ + "master": false, + + /** + * Tag names that are used for creating collections and buttons + * @namesapce + */ + "tags": {} + }; + + + /** + * @namespace Common and useful DOM elements for the class instance + */ + this.dom = { + /** + * DIV element that is create and all TableTools buttons (and their children) put into + * @property container + * @type node + * @default null + */ + "container": null, + + /** + * The table node to which TableTools will be applied + * @property table + * @type node + * @default null + */ + "table": null, + + /** + * @namespace Nodes used for the print display + */ + "print": { + /** + * Nodes which have been removed from the display by setting them to display none + * @property hidden + * @type array + * @default [] + */ + "hidden": [], + + /** + * The information display saying telling the user about the print display + * @property message + * @type node + * @default null + */ + "message": null + }, + + /** + * @namespace Nodes used for a collection display. This contains the currently used collection + */ + "collection": { + /** + * The div wrapper containing the buttons in the collection (i.e. the menu) + * @property collection + * @type node + * @default null + */ + "collection": null, + + /** + * Background display to provide focus and capture events + * @property background + * @type node + * @default null + */ + "background": null + } + }; + + /** + * @namespace Name space for the classes that this TableTools instance will use + * @extends TableTools.classes + */ + this.classes = $.extend( true, {}, TableTools.classes ); + if ( this.s.dt.bJUI ) + { + $.extend( true, this.classes, TableTools.classes_themeroller ); + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Retreieve the settings object from an instance + * @method fnSettings + * @returns {object} TableTools settings object + */ + this.fnSettings = function () { + return this.s; + }; + + + /* Constructor logic */ + if ( typeof oOpts == 'undefined' ) + { + oOpts = {}; + } + + this._fnConstruct( oOpts ); + + return this; +}; + + + +TableTools.prototype = { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Retreieve the settings object from an instance + * @returns {array} List of TR nodes which are currently selected + * @param {boolean} [filtered=false] Get only selected rows which are + * available given the filtering applied to the table. By default + * this is false - i.e. all rows, regardless of filtering are + selected. + */ + "fnGetSelected": function ( filtered ) + { + var + out = [], + data = this.s.dt.aoData, + displayed = this.s.dt.aiDisplay, + i, iLen; + + if ( filtered ) + { + // Only consider filtered rows + for ( i=0, iLen=displayed.length ; i 0 ) + { + sTitle = anTitle[0].innerHTML; + } + } + + /* Strip characters which the OS will object to - checking for UTF8 support in the scripting + * engine + */ + if ( "\u00A1".toString().length < 4 ) { + return sTitle.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, ""); + } else { + return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g, ""); + } + }, + + + /** + * Calculate a unity array with the column width by proportion for a set of columns to be + * included for a button. This is particularly useful for PDF creation, where we can use the + * column widths calculated by the browser to size the columns in the PDF. + * @param {Object} oConfig Button configuration object + * @returns {Array} Unity array of column ratios + */ + "fnCalcColRatios": function ( oConfig ) + { + var + aoCols = this.s.dt.aoColumns, + aColumnsInc = this._fnColumnTargets( oConfig.mColumns ), + aColWidths = [], + iWidth = 0, iTotal = 0, i, iLen; + + for ( i=0, iLen=aColumnsInc.length ; i

'+ + '

Copied '+len+' row'+plural+' to the clipboard.

', + 1500 + ); + } + } ), + + "pdf": $.extend( {}, TableTools.buttonBase, { + "sAction": "flash_pdf", + "sNewLine": "\n", + "sFileName": "*.pdf", + "sButtonClass": "DTTT_button_pdf", + "sButtonText": "PDF", + "sPdfOrientation": "portrait", + "sPdfSize": "A4", + "sPdfMessage": "", + "fnClick": function( nButton, oConfig, flash ) { + this.fnSetText( flash, + "title:"+ this.fnGetTitle(oConfig) +"\n"+ + "message:"+ oConfig.sPdfMessage +"\n"+ + "colWidth:"+ this.fnCalcColRatios(oConfig) +"\n"+ + "orientation:"+ oConfig.sPdfOrientation +"\n"+ + "size:"+ oConfig.sPdfSize +"\n"+ + "--/TableToolsOpts--\n" + + this.fnGetTableData(oConfig) + ); + } + } ), + + "print": $.extend( {}, TableTools.buttonBase, { + "sInfo": "
Print view

Please use your browser's print function to "+ + "print this table. Press escape when finished.", + "sMessage": null, + "bShowAll": true, + "sToolTip": "View print view", + "sButtonClass": "DTTT_button_print", + "sButtonText": "Print", + "fnClick": function ( nButton, oConfig ) { + this.fnPrint( true, oConfig ); + } + } ), + + "text": $.extend( {}, TableTools.buttonBase ), + + "select": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Select button", + "fnSelect": function( nButton, oConfig ) { + if ( this.fnGetSelected().length !== 0 ) { + $(nButton).removeClass( this.classes.buttons.disabled ); + } else { + $(nButton).addClass( this.classes.buttons.disabled ); + } + }, + "fnInit": function( nButton, oConfig ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } + } ), + + "select_single": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Select button", + "fnSelect": function( nButton, oConfig ) { + var iSelected = this.fnGetSelected().length; + if ( iSelected == 1 ) { + $(nButton).removeClass( this.classes.buttons.disabled ); + } else { + $(nButton).addClass( this.classes.buttons.disabled ); + } + }, + "fnInit": function( nButton, oConfig ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } + } ), + + "select_all": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Select all", + "fnClick": function( nButton, oConfig ) { + this.fnSelectAll(); + }, + "fnSelect": function( nButton, oConfig ) { + if ( this.fnGetSelected().length == this.s.dt.fnRecordsDisplay() ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } else { + $(nButton).removeClass( this.classes.buttons.disabled ); + } + } + } ), + + "select_none": $.extend( {}, TableTools.buttonBase, { + "sButtonText": "Deselect all", + "fnClick": function( nButton, oConfig ) { + this.fnSelectNone(); + }, + "fnSelect": function( nButton, oConfig ) { + if ( this.fnGetSelected().length !== 0 ) { + $(nButton).removeClass( this.classes.buttons.disabled ); + } else { + $(nButton).addClass( this.classes.buttons.disabled ); + } + }, + "fnInit": function( nButton, oConfig ) { + $(nButton).addClass( this.classes.buttons.disabled ); + } + } ), + + "ajax": $.extend( {}, TableTools.buttonBase, { + "sAjaxUrl": "/xhr.php", + "sButtonText": "Ajax button", + "fnClick": function( nButton, oConfig ) { + var sData = this.fnGetTableData(oConfig); + $.ajax( { + "url": oConfig.sAjaxUrl, + "data": [ + { "name": "tableData", "value": sData } + ], + "success": oConfig.fnAjaxComplete, + "dataType": "json", + "type": "POST", + "cache": false, + "error": function () { + alert( "Error detected when sending table data to server" ); + } + } ); + }, + "fnAjaxComplete": function( json ) { + alert( 'Ajax complete' ); + } + } ), + + "div": $.extend( {}, TableTools.buttonBase, { + "sAction": "div", + "sTag": "div", + "sButtonClass": "DTTT_nonbutton", + "sButtonText": "Text button" + } ), + + "collection": $.extend( {}, TableTools.buttonBase, { + "sAction": "collection", + "sButtonClass": "DTTT_button_collection", + "sButtonText": "Collection", + "fnClick": function( nButton, oConfig ) { + this._fnCollectionShow(nButton, oConfig); + } + } ) +}; +/* + * on* callback parameters: + * 1. node - button element + * 2. object - configuration object for this button + * 3. object - ZeroClipboard reference (flash button only) + * 4. string - Returned string from Flash (flash button only - and only on 'complete') + */ + + + +/** + * @namespace Classes used by TableTools - allows the styles to be override easily. + * Note that when TableTools initialises it will take a copy of the classes object + * and will use its internal copy for the remainder of its run time. + */ +TableTools.classes = { + "container": "DTTT_container", + "buttons": { + "normal": "DTTT_button", + "disabled": "DTTT_disabled" + }, + "collection": { + "container": "DTTT_collection", + "background": "DTTT_collection_background", + "buttons": { + "normal": "DTTT_button", + "disabled": "DTTT_disabled" + } + }, + "select": { + "table": "DTTT_selectable", + "row": "DTTT_selected" + }, + "print": { + "body": "DTTT_Print", + "info": "DTTT_print_info", + "message": "DTTT_PrintMessage" + } +}; + + +/** + * @namespace ThemeRoller classes - built in for compatibility with DataTables' + * bJQueryUI option. + */ +TableTools.classes_themeroller = { + "container": "DTTT_container ui-buttonset ui-buttonset-multi", + "buttons": { + "normal": "DTTT_button ui-button ui-state-default" + }, + "collection": { + "container": "DTTT_collection ui-buttonset ui-buttonset-multi" + } +}; + + +/** + * @namespace TableTools default settings for initialisation + */ +TableTools.DEFAULTS = { + "sSwfPath": "media/swf/copy_csv_xls_pdf.swf", + "sRowSelect": "none", + "sSelectedClass": null, + "fnPreRowSelect": null, + "fnRowSelected": null, + "fnRowDeselected": null, + "aButtons": [ "copy", "csv", "xls", "pdf", "print" ], + "oTags": { + "container": "div", + "button": "a", // We really want to use buttons here, but Firefox and IE ignore the + // click on the Flash element in the button (but not mouse[in|out]). + "liner": "span", + "collection": { + "container": "div", + "button": "a", + "liner": "span" + } + } +}; + + +/** + * Name of this class + * @constant CLASS + * @type String + * @default TableTools + */ +TableTools.prototype.CLASS = "TableTools"; + + +/** + * TableTools version + * @constant VERSION + * @type String + * @default See code + */ +TableTools.VERSION = "2.1.4"; +TableTools.prototype.VERSION = TableTools.VERSION; + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Initialisation + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Register a new feature with DataTables + */ +if ( typeof $.fn.dataTable == "function" && + typeof $.fn.dataTableExt.fnVersionCheck == "function" && + $.fn.dataTableExt.fnVersionCheck('1.9.0') ) +{ + $.fn.dataTableExt.aoFeatures.push( { + "fnInit": function( oDTSettings ) { + var oOpts = typeof oDTSettings.oInit.oTableTools != 'undefined' ? + oDTSettings.oInit.oTableTools : {}; + + var oTT = new TableTools( oDTSettings.oInstance, oOpts ); + TableTools._aInstances.push( oTT ); + + return oTT.dom.container; + }, + "cFeature": "T", + "sFeature": "TableTools" + } ); +} +else +{ + alert( "Warning: TableTools 2 requires DataTables 1.9.0 or newer - www.datatables.net/download"); +} + +$.fn.DataTable.TableTools = TableTools; + +})(jQuery, window, document); diff --git a/plugins/web_gui/static/plugins/datatables/ZeroClipboard.js b/plugins/web_gui/static/plugins/datatables/ZeroClipboard.js new file mode 100644 index 0000000..de0f6b6 --- /dev/null +++ b/plugins/web_gui/static/plugins/datatables/ZeroClipboard.js @@ -0,0 +1,367 @@ +// Simple Set Clipboard System +// Author: Joseph Huckaby + +var ZeroClipboard_TableTools = { + + version: "1.0.4-TableTools2", + clients: {}, // registered upload clients on page, indexed by id + moviePath: '', // URL to movie + nextId: 1, // ID of next movie + + $: function(thingy) { + // simple DOM lookup utility function + if (typeof(thingy) == 'string') thingy = document.getElementById(thingy); + if (!thingy.addClass) { + // extend element with a few useful methods + thingy.hide = function() { this.style.display = 'none'; }; + thingy.show = function() { this.style.display = ''; }; + thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; + thingy.removeClass = function(name) { + this.className = this.className.replace( new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, ''); + }; + thingy.hasClass = function(name) { + return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); + } + } + return thingy; + }, + + setMoviePath: function(path) { + // set path to ZeroClipboard.swf + this.moviePath = path; + }, + + dispatch: function(id, eventName, args) { + // receive event from flash movie, send to client + var client = this.clients[id]; + if (client) { + client.receiveEvent(eventName, args); + } + }, + + register: function(id, client) { + // register new client to receive events + this.clients[id] = client; + }, + + getDOMObjectPosition: function(obj) { + // get absolute coordinates for dom element + var info = { + left: 0, + top: 0, + width: obj.width ? obj.width : obj.offsetWidth, + height: obj.height ? obj.height : obj.offsetHeight + }; + + if ( obj.style.width != "" ) + info.width = obj.style.width.replace("px",""); + + if ( obj.style.height != "" ) + info.height = obj.style.height.replace("px",""); + + while (obj) { + info.left += obj.offsetLeft; + info.top += obj.offsetTop; + obj = obj.offsetParent; + } + + return info; + }, + + Client: function(elem) { + // constructor for new simple upload client + this.handlers = {}; + + // unique ID + this.id = ZeroClipboard_TableTools.nextId++; + this.movieId = 'ZeroClipboard_TableToolsMovie_' + this.id; + + // register client with singleton to receive flash events + ZeroClipboard_TableTools.register(this.id, this); + + // create movie + if (elem) this.glue(elem); + } +}; + +ZeroClipboard_TableTools.Client.prototype = { + + id: 0, // unique ID for us + ready: false, // whether movie is ready to receive events or not + movie: null, // reference to movie object + clipText: '', // text to copy to clipboard + fileName: '', // default file save name + action: 'copy', // action to perform + handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor + cssEffects: true, // enable CSS mouse effects on dom container + handlers: null, // user event handlers + sized: false, + + glue: function(elem, title) { + // glue to DOM element + // elem can be ID or actual DOM element object + this.domElement = ZeroClipboard_TableTools.$(elem); + + // float just above object, or zIndex 99 if dom element isn't set + var zIndex = 99; + if (this.domElement.style.zIndex) { + zIndex = parseInt(this.domElement.style.zIndex) + 1; + } + + // find X/Y position of domElement + var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement); + + // create floating DIV above element + this.div = document.createElement('div'); + var style = this.div.style; + style.position = 'absolute'; + style.left = '0px'; + style.top = '0px'; + style.width = (box.width) + 'px'; + style.height = box.height + 'px'; + style.zIndex = zIndex; + + if ( typeof title != "undefined" && title != "" ) { + this.div.title = title; + } + if ( box.width != 0 && box.height != 0 ) { + this.sized = true; + } + + // style.backgroundColor = '#f00'; // debug + if ( this.domElement ) { + this.domElement.appendChild(this.div); + this.div.innerHTML = this.getHTML( box.width, box.height ); + } + }, + + positionElement: function() { + var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement); + var style = this.div.style; + + style.position = 'absolute'; + //style.left = (this.domElement.offsetLeft)+'px'; + //style.top = this.domElement.offsetTop+'px'; + style.width = box.width + 'px'; + style.height = box.height + 'px'; + + if ( box.width != 0 && box.height != 0 ) { + this.sized = true; + } else { + return; + } + + var flash = this.div.childNodes[0]; + flash.width = box.width; + flash.height = box.height; + }, + + getHTML: function(width, height) { + // return HTML for movie + var html = ''; + var flashvars = 'id=' + this.id + + '&width=' + width + + '&height=' + height; + + if (navigator.userAgent.match(/MSIE/)) { + // IE gets an OBJECT tag + var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; + html += ''; + } + else { + // all other browsers get an EMBED tag + html += ''; + } + return html; + }, + + hide: function() { + // temporarily hide floater offscreen + if (this.div) { + this.div.style.left = '-2000px'; + } + }, + + show: function() { + // show ourselves after a call to hide() + this.reposition(); + }, + + destroy: function() { + // destroy control and floater + if (this.domElement && this.div) { + this.hide(); + this.div.innerHTML = ''; + + var body = document.getElementsByTagName('body')[0]; + try { body.removeChild( this.div ); } catch(e) {;} + + this.domElement = null; + this.div = null; + } + }, + + reposition: function(elem) { + // reposition our floating div, optionally to new container + // warning: container CANNOT change size, only position + if (elem) { + this.domElement = ZeroClipboard_TableTools.$(elem); + if (!this.domElement) this.hide(); + } + + if (this.domElement && this.div) { + var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement); + var style = this.div.style; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + } + }, + + clearText: function() { + // clear the text to be copy / saved + this.clipText = ''; + if (this.ready) this.movie.clearText(); + }, + + appendText: function(newText) { + // append text to that which is to be copied / saved + this.clipText += newText; + if (this.ready) { this.movie.appendText(newText) ;} + }, + + setText: function(newText) { + // set text to be copied to be copied / saved + this.clipText = newText; + if (this.ready) { this.movie.setText(newText) ;} + }, + + setCharSet: function(charSet) { + // set the character set (UTF16LE or UTF8) + this.charSet = charSet; + if (this.ready) { this.movie.setCharSet(charSet) ;} + }, + + setBomInc: function(bomInc) { + // set if the BOM should be included or not + this.incBom = bomInc; + if (this.ready) { this.movie.setBomInc(bomInc) ;} + }, + + setFileName: function(newText) { + // set the file name + this.fileName = newText; + if (this.ready) this.movie.setFileName(newText); + }, + + setAction: function(newText) { + // set action (save or copy) + this.action = newText; + if (this.ready) this.movie.setAction(newText); + }, + + addEventListener: function(eventName, func) { + // add user event listener for event + // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + if (!this.handlers[eventName]) this.handlers[eventName] = []; + this.handlers[eventName].push(func); + }, + + setHandCursor: function(enabled) { + // enable hand cursor (true), or default arrow cursor (false) + this.handCursorEnabled = enabled; + if (this.ready) this.movie.setHandCursor(enabled); + }, + + setCSSEffects: function(enabled) { + // enable or disable CSS effects on DOM container + this.cssEffects = !!enabled; + }, + + receiveEvent: function(eventName, args) { + // receive event from flash + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + + // special behavior for certain events + switch (eventName) { + case 'load': + // movie claims it is ready, but in IE this isn't always the case... + // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function + this.movie = document.getElementById(this.movieId); + if (!this.movie) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 1 ); + return; + } + + // firefox on pc needs a "kick" in order to set these in certain cases + if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 100 ); + this.ready = true; + return; + } + + this.ready = true; + this.movie.clearText(); + this.movie.appendText( this.clipText ); + this.movie.setFileName( this.fileName ); + this.movie.setAction( this.action ); + this.movie.setCharSet( this.charSet ); + this.movie.setBomInc( this.incBom ); + this.movie.setHandCursor( this.handCursorEnabled ); + break; + + case 'mouseover': + if (this.domElement && this.cssEffects) { + //this.domElement.addClass('hover'); + if (this.recoverActive) this.domElement.addClass('active'); + } + break; + + case 'mouseout': + if (this.domElement && this.cssEffects) { + this.recoverActive = false; + if (this.domElement.hasClass('active')) { + this.domElement.removeClass('active'); + this.recoverActive = true; + } + //this.domElement.removeClass('hover'); + } + break; + + case 'mousedown': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('active'); + } + break; + + case 'mouseup': + if (this.domElement && this.cssEffects) { + this.domElement.removeClass('active'); + this.recoverActive = false; + } + break; + } // switch eventName + + if (this.handlers[eventName]) { + for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { + var func = this.handlers[eventName][idx]; + + if (typeof(func) == 'function') { + // actual function reference + func(this, args); + } + else if ((typeof(func) == 'object') && (func.length == 2)) { + // PHP style object + method, i.e. [myObject, 'myMethod'] + func[0][ func[1] ](this, args); + } + else if (typeof(func) == 'string') { + // name of function + window[func](this, args); + } + } // foreach event handler defined + } // user defined handler for event + } + +}; diff --git a/plugins/web_gui/static/plugins/datatables/copy_csv_xls_pdf.swf b/plugins/web_gui/static/plugins/datatables/copy_csv_xls_pdf.swf new file mode 100644 index 0000000000000000000000000000000000000000..75dd21ae55e09022a40759df0d1d6cdffc2eed62 GIT binary patch literal 58827 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 literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/datatables/dataTables.bootstrap.js b/plugins/web_gui/static/plugins/datatables/dataTables.bootstrap.js new file mode 100644 index 0000000..6b25605 --- /dev/null +++ b/plugins/web_gui/static/plugins/datatables/dataTables.bootstrap.js @@ -0,0 +1,148 @@ +/* Set the defaults for DataTables initialisation */ +$.extend( true, $.fn.dataTable.defaults, { + "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>", + "sPaginationType": "bootstrap", + "oLanguage": { + "sLengthMenu": "_MENU_ records per page" + } +} ); + + +/* Default class modification */ +$.extend( $.fn.dataTableExt.oStdClasses, { + "sWrapper": "dataTables_wrapper form-inline" +} ); + + +/* API method to get paging information */ +$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings ) +{ + return { + "iStart": oSettings._iDisplayStart, + "iEnd": oSettings.fnDisplayEnd(), + "iLength": oSettings._iDisplayLength, + "iTotal": oSettings.fnRecordsTotal(), + "iFilteredTotal": oSettings.fnRecordsDisplay(), + "iPage": oSettings._iDisplayLength === -1 ? + 0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ), + "iTotalPages": oSettings._iDisplayLength === -1 ? + 0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength ) + }; +}; + + +/* Bootstrap style pagination control */ +$.extend( $.fn.dataTableExt.oPagination, { + "bootstrap": { + "fnInit": function( oSettings, nPaging, fnDraw ) { + var oLang = oSettings.oLanguage.oPaginate; + var fnClickHandler = function ( e ) { + e.preventDefault(); + if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) { + fnDraw( oSettings ); + } + }; + + $(nPaging).append( + '

' + ); + var els = $('a', nPaging); + $(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler ); + $(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler ); + }, + + "fnUpdate": function ( oSettings, fnDraw ) { + var iListLength = 5; + var oPaging = oSettings.oInstance.fnPagingInfo(); + var an = oSettings.aanFeatures.p; + var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2); + + if ( oPaging.iTotalPages < iListLength) { + iStart = 1; + iEnd = oPaging.iTotalPages; + } + else if ( oPaging.iPage <= iHalf ) { + iStart = 1; + iEnd = iListLength; + } else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) { + iStart = oPaging.iTotalPages - iListLength + 1; + iEnd = oPaging.iTotalPages; + } else { + iStart = oPaging.iPage - iHalf + 1; + iEnd = iStart + iListLength - 1; + } + + for ( i=0, ien=an.length ; i'+j+'') + .insertBefore( $('li:last', an[i])[0] ) + .bind('click', function (e) { + e.preventDefault(); + oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength; + fnDraw( oSettings ); + } ); + } + + // Add / remove disabled classes from the static elements + if ( oPaging.iPage === 0 ) { + $('li:first', an[i]).addClass('disabled'); + } else { + $('li:first', an[i]).removeClass('disabled'); + } + + if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) { + $('li:last', an[i]).addClass('disabled'); + } else { + $('li:last', an[i]).removeClass('disabled'); + } + } + } + } +} ); + + +/* + * TableTools Bootstrap compatibility + * Required TableTools 2.1+ + */ +if ( $.fn.DataTable.TableTools ) { + // Set the classes that TableTools uses to something suitable for Bootstrap + $.extend( true, $.fn.DataTable.TableTools.classes, { + "container": "DTTT btn-group", + "buttons": { + "normal": "btn", + "disabled": "disabled" + }, + "collection": { + "container": "DTTT_dropdown dropdown-menu", + "buttons": { + "normal": "", + "disabled": "disabled" + } + }, + "print": { + "info": "DTTT_print_info modal" + }, + "select": { + "row": "active" + } + } ); + + // Have the collection use a bootstrap compatible dropdown + $.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, { + "collection": { + "container": "ul", + "button": "li", + "liner": "a" + } + } ); +} + diff --git a/plugins/web_gui/static/plugins/datatables/jquery.dataTables.js b/plugins/web_gui/static/plugins/datatables/jquery.dataTables.js new file mode 100644 index 0000000..1d8a220 --- /dev/null +++ b/plugins/web_gui/static/plugins/datatables/jquery.dataTables.js @@ -0,0 +1,12099 @@ +/** + * @summary DataTables + * @description Paginate, search and sort HTML tables + * @version 1.9.4 + * @file jquery.dataTables.js + * @author Allan Jardine (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * + * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/*jslint evil: true, undef: true, browser: true */ +/*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/ + +(/** @lends */function( window, document, undefined ) { + +(function( factory ) { + "use strict"; + + // Define as an AMD module if possible + if ( typeof define === 'function' && define.amd ) + { + define( ['jquery'], factory ); + } + /* Define using browser globals otherwise + * Prevent multiple instantiations if the script is loaded twice + */ + else if ( jQuery && !jQuery.fn.dataTable ) + { + factory( jQuery ); + } +} +(/** @lends */function( $ ) { + "use strict"; + /** + * DataTables is a plug-in for the jQuery Javascript library. It is a + * highly flexible tool, based upon the foundations of progressive + * enhancement, which will add advanced interaction controls to any + * HTML table. For a full list of features please refer to + * DataTables.net. + * + * Note that the DataTable object is not a global variable but is + * aliased to jQuery.fn.DataTable and jQuery.fn.dataTable through which + * it may be accessed. + * + * @class + * @param {object} [oInit={}] Configuration object for DataTables. Options + * are defined by {@link DataTable.defaults} + * @requires jQuery 1.3+ + * + * @example + * // Basic initialisation + * $(document).ready( function { + * $('#example').dataTable(); + * } ); + * + * @example + * // Initialisation with configuration options - in this case, disable + * // pagination and sorting. + * $(document).ready( function { + * $('#example').dataTable( { + * "bPaginate": false, + * "bSort": false + * } ); + * } ); + */ + var DataTable = function( oInit ) + { + + + /** + * Add a column to the list used for the table with default values + * @param {object} oSettings dataTables settings object + * @param {node} nTh The th element for this column + * @memberof DataTable#oApi + */ + function _fnAddColumn( oSettings, nTh ) + { + var oDefaults = DataTable.defaults.columns; + var iCol = oSettings.aoColumns.length; + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { + "sSortingClass": oSettings.oClasses.sSortable, + "sSortingClassJUI": oSettings.oClasses.sSortJUI, + "nTh": nTh ? nTh : document.createElement('th'), + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], + "mData": oDefaults.mData ? oDefaults.oDefaults : iCol + } ); + oSettings.aoColumns.push( oCol ); + + /* Add a column specific filter */ + if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null ) + { + oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch ); + } + else + { + var oPre = oSettings.aoPreSearchCols[ iCol ]; + + /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */ + if ( oPre.bRegex === undefined ) + { + oPre.bRegex = true; + } + + if ( oPre.bSmart === undefined ) + { + oPre.bSmart = true; + } + + if ( oPre.bCaseInsensitive === undefined ) + { + oPre.bCaseInsensitive = true; + } + } + + /* Use the column options function to initialise classes etc */ + _fnColumnOptions( oSettings, iCol, null ); + } + + + /** + * Apply options for a column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column index to consider + * @param {object} oOptions object with sType, bVisible and bSearchable etc + * @memberof DataTable#oApi + */ + function _fnColumnOptions( oSettings, iCol, oOptions ) + { + var oCol = oSettings.aoColumns[ iCol ]; + + /* User specified column options */ + if ( oOptions !== undefined && oOptions !== null ) + { + /* Backwards compatibility for mDataProp */ + if ( oOptions.mDataProp && !oOptions.mData ) + { + oOptions.mData = oOptions.mDataProp; + } + + if ( oOptions.sType !== undefined ) + { + oCol.sType = oOptions.sType; + oCol._bAutoType = false; + } + + $.extend( oCol, oOptions ); + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); + + /* iDataSort to be applied (backwards compatibility), but aDataSort will take + * priority if defined + */ + if ( oOptions.iDataSort !== undefined ) + { + oCol.aDataSort = [ oOptions.iDataSort ]; + } + _fnMap( oCol, oOptions, "aDataSort" ); + } + + /* Cache the data get and set functions for speed */ + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; + var mData = _fnGetObjectDataFn( oCol.mData ); + + oCol.fnGetData = function (oData, sSpecific) { + var innerData = mData( oData, sSpecific ); + + if ( oCol.mRender && (sSpecific && sSpecific !== '') ) + { + return mRender( innerData, sSpecific, oData ); + } + return innerData; + }; + oCol.fnSetData = _fnSetObjectDataFn( oCol.mData ); + + /* Feature sorting overrides column specific when off */ + if ( !oSettings.oFeatures.bSort ) + { + oCol.bSortable = false; + } + + /* Check that the class assignment is correct for sorting */ + if ( !oCol.bSortable || + ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableNone; + oCol.sSortingClassJUI = ""; + } + else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortable; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI; + } + else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableAsc; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed; + } + else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableDesc; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed; + } + } + + + /** + * Adjust the table column widths for new data. Note: you would probably want to + * do a redraw after calling this function! + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAdjustColumnSizing ( oSettings ) + { + /* Not interested in doing column width calculation if auto-width is disabled */ + if ( oSettings.oFeatures.bAutoWidth === false ) + { + return false; + } + + _fnCalculateColumnWidths( oSettings ); + for ( var i=0 , iLen=oSettings.aoColumns.length ; i
for filtering data. + *
    + *
  • + * Function input parameters: + *
      + *
    • {*} Data from the column cell to be prepared for filtering
    • + *
    + *
  • + *
  • + * Function return: + *
      + *
    • {string|null} Formatted string that will be used for the filtering.
    • + *
    + * + *
+ * + * Note that as of v1.9, it is typically preferable to use mData to prepare data for + * the different uses that DataTables can put the data to. Specifically mData when + * used as a function will give you a 'type' (sorting, filtering etc) that you can use to + * prepare the data as required for the different types. As such, this method is deprecated. + * @type object + * @default {} + * @deprecated + * + * @example + * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) { + * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" ); + * } + */ + "ofnSearch": {}, + + + /** + * Container for all private functions in DataTables so they can be exposed externally + * @type object + * @default {} + */ + "oApi": {}, + + + /** + * Storage for the various classes that DataTables uses + * @type object + * @default {} + */ + "oStdClasses": {}, + + + /** + * Storage for the various classes that DataTables uses - jQuery UI suitable + * @type object + * @default {} + */ + "oJUIClasses": {}, + + + /** + * Pagination plug-in methods - The style and controls of the pagination can significantly + * impact on how the end user interacts with the data in your table, and DataTables allows + * the addition of pagination controls by extending this object, which can then be enabled + * through the sPaginationType initialisation parameter. Each pagination type that + * is added is an object (the property name of which is what sPaginationType refers + * to) that has two properties, both methods that are used by DataTables to update the + * control's state. + *
    + *
  • + * fnInit - Initialisation of the paging controls. Called only during initialisation + * of the table. It is expected that this function will add the required DOM elements + * to the page for the paging controls to work. The element pointer + * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging + * controls (note that this is a 2D array to allow for multiple instances of each + * DataTables DOM element). It is suggested that you add the controls to this element + * as children + *
      + *
    • + * Function input parameters: + *
        + *
      • {object} DataTables settings object: see {@link DataTable.models.oSettings}.
      • + *
      • {node} Container into which the pagination controls must be inserted
      • + *
      • {function} Draw callback function - whenever the controls cause a page + * change, this method must be called to redraw the table.
      • + *
      + *
    • + *
    • + * Function return: + *
        + *
      • No return required
      • + *
      + * + *
    + * + *
  • + * fnInit - This function is called whenever the paging status of the table changes and is + * typically used to update classes and/or text of the paging controls to reflex the new + * status. + *
      + *
    • + * Function input parameters: + *
        + *
      • {object} DataTables settings object: see {@link DataTable.models.oSettings}.
      • + *
      • {function} Draw callback function - in case you need to redraw the table again + * or attach new event listeners
      • + *
      + *
    • + *
    • + * Function return: + *
        + *
      • No return required
      • + *
      + * + *
    + * + *
+ * @type object + * @default {} + * + * @example + * $.fn.dataTableExt.oPagination.four_button = { + * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) { + * nFirst = document.createElement( 'span' ); + * nPrevious = document.createElement( 'span' ); + * nNext = document.createElement( 'span' ); + * nLast = document.createElement( 'span' ); + * + * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) ); + * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) ); + * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) ); + * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) ); + * + * nFirst.className = "paginate_button first"; + * nPrevious.className = "paginate_button previous"; + * nNext.className="paginate_button next"; + * nLast.className = "paginate_button last"; + * + * nPaging.appendChild( nFirst ); + * nPaging.appendChild( nPrevious ); + * nPaging.appendChild( nNext ); + * nPaging.appendChild( nLast ); + * + * $(nFirst).click( function () { + * oSettings.oApi._fnPageChange( oSettings, "first" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nPrevious).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "previous" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nNext).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "next" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nLast).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "last" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nFirst).bind( 'selectstart', function () { return false; } ); + * $(nPrevious).bind( 'selectstart', function () { return false; } ); + * $(nNext).bind( 'selectstart', function () { return false; } ); + * $(nLast).bind( 'selectstart', function () { return false; } ); + * }, + * + * "fnUpdate": function ( oSettings, fnCallbackDraw ) { + * if ( !oSettings.aanFeatures.p ) { + * return; + * } + * + * // Loop over each instance of the pager + * var an = oSettings.aanFeatures.p; + * for ( var i=0, iLen=an.length ; i + *
  • + * Function input parameters: + *
      + *
    • {*} Data to compare to the second parameter
    • + *
    • {*} Data to compare to the first parameter
    • + *
    + *
  • + *
  • + * Function return: + *
      + *
    • {int} Sorting match: <0 if first parameter should be sorted lower than + * the second parameter, ===0 if the two parameters are equal and >0 if + * the first parameter should be sorted height than the second parameter.
    • + *
    + * + * + * @type object + * @default {} + * + * @example + * // Case-sensitive string sorting, with no pre-formatting method + * $.extend( $.fn.dataTableExt.oSort, { + * "string-case-asc": function(x,y) { + * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + * }, + * "string-case-desc": function(x,y) { + * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + * } + * } ); + * + * @example + * // Case-insensitive string sorting, with pre-formatting + * $.extend( $.fn.dataTableExt.oSort, { + * "string-pre": function(x) { + * return x.toLowerCase(); + * }, + * "string-asc": function(x,y) { + * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + * }, + * "string-desc": function(x,y) { + * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + * } + * } ); + */ + "oSort": {}, + + + /** + * Version string for plug-ins to check compatibility. Allowed format is + * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and + * e are optional + * @type string + * @default Version number + */ + "sVersion": DataTable.version, + + + /** + * How should DataTables report an error. Can take the value 'alert' or 'throw' + * @type string + * @default alert + */ + "sErrMode": "alert", + + + /** + * Store information for DataTables to access globally about other instances + * @namespace + * @private + */ + "_oExternConfig": { + /* int:iNextUnique - next unique number for an instance */ + "iNextUnique": 0 + } + }; + + + + + /** + * Template object for the way in which DataTables holds information about + * search information for the global filter and individual column filters. + * @namespace + */ + DataTable.models.oSearch = { + /** + * Flag to indicate if the filtering should be case insensitive or not + * @type boolean + * @default true + */ + "bCaseInsensitive": true, + + /** + * Applied search term + * @type string + * @default Empty string + */ + "sSearch": "", + + /** + * Flag to indicate if the search term should be interpreted as a + * regular expression (true) or not (false) and therefore and special + * regex characters escaped. + * @type boolean + * @default false + */ + "bRegex": false, + + /** + * Flag to indicate if DataTables is to use its smart filtering or not. + * @type boolean + * @default true + */ + "bSmart": true + }; + + + + + /** + * Template object for the way in which DataTables holds information about + * each individual row. This is the object format used for the settings + * aoData array. + * @namespace + */ + DataTable.models.oRow = { + /** + * TR element for the row + * @type node + * @default null + */ + "nTr": null, + + /** + * Data object from the original data source for the row. This is either + * an array if using the traditional form of DataTables, or an object if + * using mData options. The exact type will depend on the passed in + * data from the data source, or will be an array if using DOM a data + * source. + * @type array|object + * @default [] + */ + "_aData": [], + + /** + * Sorting data cache - this array is ostensibly the same length as the + * number of columns (although each index is generated only as it is + * needed), and holds the data that is used for sorting each column in the + * row. We do this cache generation at the start of the sort in order that + * the formatting of the sort data need be done only once for each cell + * per sort. This array should not be read from or written to by anything + * other than the master sorting methods. + * @type array + * @default [] + * @private + */ + "_aSortData": [], + + /** + * Array of TD elements that are cached for hidden rows, so they can be + * reinserted into the table if a column is made visible again (or to act + * as a store if a column is made hidden). Only hidden columns have a + * reference in the array. For non-hidden columns the value is either + * undefined or null. + * @type array nodes + * @default [] + * @private + */ + "_anHidden": [], + + /** + * Cache of the class name that DataTables has applied to the row, so we + * can quickly look at this variable rather than needing to do a DOM check + * on className for the nTr property. + * @type string + * @default Empty string + * @private + */ + "_sRowStripe": "" + }; + + + + /** + * Template object for the column information object in DataTables. This object + * is held in the settings aoColumns array and contains all the information that + * DataTables needs about each individual column. + * + * Note that this object is related to {@link DataTable.defaults.columns} + * but this one is the internal data store for DataTables's cache of columns. + * It should NOT be manipulated outside of DataTables. Any configuration should + * be done through the initialisation options. + * @namespace + */ + DataTable.models.oColumn = { + /** + * A list of the columns that sorting should occur on when this column + * is sorted. That this property is an array allows multi-column sorting + * to be defined for a column (for example first name / last name columns + * would benefit from this). The values are integers pointing to the + * columns to be sorted on (typically it will be a single integer pointing + * at itself, but that doesn't need to be the case). + * @type array + */ + "aDataSort": null, + + /** + * Define the sorting directions that are applied to the column, in sequence + * as the column is repeatedly sorted upon - i.e. the first value is used + * as the sorting direction when the column if first sorted (clicked on). + * Sort it again (click again) and it will move on to the next index. + * Repeat until loop. + * @type array + */ + "asSorting": null, + + /** + * Flag to indicate if the column is searchable, and thus should be included + * in the filtering or not. + * @type boolean + */ + "bSearchable": null, + + /** + * Flag to indicate if the column is sortable or not. + * @type boolean + */ + "bSortable": null, + + /** + * Deprecated When using fnRender, you have two options for what + * to do with the data, and this property serves as the switch. Firstly, you + * can have the sorting and filtering use the rendered value (true - default), + * or you can have the sorting and filtering us the original value (false). + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type boolean + * @deprecated + */ + "bUseRendered": null, + + /** + * Flag to indicate if the column is currently visible in the table or not + * @type boolean + */ + "bVisible": null, + + /** + * Flag to indicate to the type detection method if the automatic type + * detection should be used, or if a column type (sType) has been specified + * @type boolean + * @default true + * @private + */ + "_bAutoType": true, + + /** + * Developer definable function that is called whenever a cell is created (Ajax source, + * etc) or processed for input (DOM source). This can be used as a compliment to mRender + * allowing you to modify the DOM element (add background colour for example) when the + * element is available. + * @type function + * @param {element} nTd The TD node that has been created + * @param {*} sData The Data for the cell + * @param {array|object} oData The data for the whole row + * @param {int} iRow The row index for the aoData data store + * @default null + */ + "fnCreatedCell": null, + + /** + * Function to get data from a cell in a column. You should never + * access data directly through _aData internally in DataTables - always use + * the method attached to this property. It allows mData to function as + * required. This function is automatically assigned by the column + * initialisation method + * @type function + * @param {array|object} oData The data array/object for the array + * (i.e. aoData[]._aData) + * @param {string} sSpecific The specific data type you want to get - + * 'display', 'type' 'filter' 'sort' + * @returns {*} The data for the cell from the given row's data + * @default null + */ + "fnGetData": null, + + /** + * Deprecated Custom display function that will be called for the + * display of each cell in this column. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type function + * @param {object} o Object with the following parameters: + * @param {int} o.iDataRow The row in aoData + * @param {int} o.iDataColumn The column in question + * @param {array} o.aData The data for the row in question + * @param {object} o.oSettings The settings object for this DataTables instance + * @returns {string} The string you which to use in the display + * @default null + * @deprecated + */ + "fnRender": null, + + /** + * Function to set data for a cell in the column. You should never + * set the data directly to _aData internally in DataTables - always use + * this method. It allows mData to function as required. This function + * is automatically assigned by the column initialisation method + * @type function + * @param {array|object} oData The data array/object for the array + * (i.e. aoData[]._aData) + * @param {*} sValue Value to set + * @default null + */ + "fnSetData": null, + + /** + * Property to read the value for the cells in the column from the data + * source array / object. If null, then the default content is used, if a + * function is given then the return from the function is used. + * @type function|int|string|null + * @default null + */ + "mData": null, + + /** + * Partner property to mData which is used (only when defined) to get + * the data - i.e. it is basically the same as mData, but without the + * 'set' option, and also the data fed to it is the result from mData. + * This is the rendering method to match the data method of mData. + * @type function|int|string|null + * @default null + */ + "mRender": null, + + /** + * Unique header TH/TD element for this column - this is what the sorting + * listener is attached to (if sorting is enabled.) + * @type node + * @default null + */ + "nTh": null, + + /** + * Unique footer TH/TD element for this column (if there is one). Not used + * in DataTables as such, but can be used for plug-ins to reference the + * footer for each column. + * @type node + * @default null + */ + "nTf": null, + + /** + * The class to apply to all TD elements in the table's TBODY for the column + * @type string + * @default null + */ + "sClass": null, + + /** + * When DataTables calculates the column widths to assign to each column, + * it finds the longest string in each column and then constructs a + * temporary table and reads the widths from that. The problem with this + * is that "mmm" is much wider then "iiii", but the latter is a longer + * string - thus the calculation can go wrong (doing it properly and putting + * it into an DOM object and measuring that is horribly(!) slow). Thus as + * a "work around" we provide this option. It will append its value to the + * text that is found to be the longest string for the column - i.e. padding. + * @type string + */ + "sContentPadding": null, + + /** + * Allows a default value to be given for a column's data, and will be used + * whenever a null data source is encountered (this can be because mData + * is set to null, or because the data source itself is null). + * @type string + * @default null + */ + "sDefaultContent": null, + + /** + * Name for the column, allowing reference to the column by name as well as + * by index (needs a lookup to work by name). + * @type string + */ + "sName": null, + + /** + * Custom sorting data type - defines which of the available plug-ins in + * afnSortData the custom sorting will use - if any is defined. + * @type string + * @default std + */ + "sSortDataType": 'std', + + /** + * Class to be applied to the header element when sorting on this column + * @type string + * @default null + */ + "sSortingClass": null, + + /** + * Class to be applied to the header element when sorting on this column - + * when jQuery UI theming is used. + * @type string + * @default null + */ + "sSortingClassJUI": null, + + /** + * Title of the column - what is seen in the TH element (nTh). + * @type string + */ + "sTitle": null, + + /** + * Column sorting and filtering type + * @type string + * @default null + */ + "sType": null, + + /** + * Width of the column + * @type string + * @default null + */ + "sWidth": null, + + /** + * Width of the column when it was first "encountered" + * @type string + * @default null + */ + "sWidthOrig": null + }; + + + + /** + * Initialisation options that can be given to DataTables at initialisation + * time. + * @namespace + */ + DataTable.defaults = { + /** + * An array of data to use for the table, passed in at initialisation which + * will be used in preference to any data which is already in the DOM. This is + * particularly useful for constructing tables purely in Javascript, for + * example with a custom Ajax call. + * @type array + * @default null + * @dtopt Option + * + * @example + * // Using a 2D array data source + * $(document).ready( function () { + * $('#example').dataTable( { + * "aaData": [ + * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], + * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], + * ], + * "aoColumns": [ + * { "sTitle": "Engine" }, + * { "sTitle": "Browser" }, + * { "sTitle": "Platform" }, + * { "sTitle": "Version" }, + * { "sTitle": "Grade" } + * ] + * } ); + * } ); + * + * @example + * // Using an array of objects as a data source (mData) + * $(document).ready( function () { + * $('#example').dataTable( { + * "aaData": [ + * { + * "engine": "Trident", + * "browser": "Internet Explorer 4.0", + * "platform": "Win 95+", + * "version": 4, + * "grade": "X" + * }, + * { + * "engine": "Trident", + * "browser": "Internet Explorer 5.0", + * "platform": "Win 95+", + * "version": 5, + * "grade": "C" + * } + * ], + * "aoColumns": [ + * { "sTitle": "Engine", "mData": "engine" }, + * { "sTitle": "Browser", "mData": "browser" }, + * { "sTitle": "Platform", "mData": "platform" }, + * { "sTitle": "Version", "mData": "version" }, + * { "sTitle": "Grade", "mData": "grade" } + * ] + * } ); + * } ); + */ + "aaData": null, + + + /** + * If sorting is enabled, then DataTables will perform a first pass sort on + * initialisation. You can define which column(s) the sort is performed upon, + * and the sorting direction, with this variable. The aaSorting array should + * contain an array for each column to be sorted initially containing the + * column's index and a direction string ('asc' or 'desc'). + * @type array + * @default [[0,'asc']] + * @dtopt Option + * + * @example + * // Sort by 3rd column first, and then 4th column + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSorting": [[2,'asc'], [3,'desc']] + * } ); + * } ); + * + * // No initial sorting + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSorting": [] + * } ); + * } ); + */ + "aaSorting": [[0,'asc']], + + + /** + * This parameter is basically identical to the aaSorting parameter, but + * cannot be overridden by user interaction with the table. What this means + * is that you could have a column (visible or hidden) which the sorting will + * always be forced on first - any sorting after that (from the user) will + * then be performed as required. This can be useful for grouping rows + * together. + * @type array + * @default null + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSortingFixed": [[0,'asc']] + * } ); + * } ) + */ + "aaSortingFixed": null, + + + /** + * This parameter allows you to readily specify the entries in the length drop + * down menu that DataTables shows when pagination is enabled. It can be + * either a 1D array of options which will be used for both the displayed + * option and the value, or a 2D array which will use the array in the first + * position as the value, and the array in the second position as the + * displayed options (useful for language strings such as 'All'). + * @type array + * @default [ 10, 25, 50, 100 ] + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] + * } ); + * } ); + * + * @example + * // Setting the default display length as well as length menu + * // This is likely to be wanted if you remove the '10' option which + * // is the iDisplayLength default. + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayLength": 25, + * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]] + * } ); + * } ); + */ + "aLengthMenu": [ 10, 25, 50, 100 ], + + + /** + * The aoColumns option in the initialisation parameter allows you to define + * details about the way individual columns behave. For a full list of + * column options that can be set, please see + * {@link DataTable.defaults.columns}. Note that if you use aoColumns to + * define your columns, you must have an entry in the array for every single + * column that you have in your table (these can be null if you don't which + * to specify any options). + * @member + */ + "aoColumns": null, + + /** + * Very similar to aoColumns, aoColumnDefs allows you to target a specific + * column, multiple columns, or all columns, using the aTargets property of + * each object in the array. This allows great flexibility when creating + * tables, as the aoColumnDefs arrays can be of any length, targeting the + * columns you specifically want. aoColumnDefs may use any of the column + * options available: {@link DataTable.defaults.columns}, but it _must_ + * have aTargets defined in each object in the array. Values in the aTargets + * array may be: + *
      + *
    • a string - class name will be matched on the TH for the column
    • + *
    • 0 or a positive integer - column index counting from the left
    • + *
    • a negative integer - column index counting from the right
    • + *
    • the string "_all" - all columns (i.e. assign a default)
    • + *
    + * @member + */ + "aoColumnDefs": null, + + + /** + * Basically the same as oSearch, this parameter defines the individual column + * filtering state at initialisation time. The array must be of the same size + * as the number of columns, and each element be an object with the parameters + * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also + * accepted and the default will be used. + * @type array + * @default [] + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoSearchCols": [ + * null, + * { "sSearch": "My filter" }, + * null, + * { "sSearch": "^[0-9]", "bEscapeRegex": false } + * ] + * } ); + * } ) + */ + "aoSearchCols": [], + + + /** + * An array of CSS classes that should be applied to displayed rows. This + * array may be of any length, and DataTables will apply each class + * sequentially, looping when required. + * @type array + * @default null Will take the values determined by the oClasses.sStripe* + * options + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ] + * } ); + * } ) + */ + "asStripeClasses": null, + + + /** + * Enable or disable automatic column width calculation. This can be disabled + * as an optimisation (it takes some time to calculate the widths) if the + * tables widths are passed in using aoColumns. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bAutoWidth": false + * } ); + * } ); + */ + "bAutoWidth": true, + + + /** + * Deferred rendering can provide DataTables with a huge speed boost when you + * are using an Ajax or JS data source for the table. This option, when set to + * true, will cause DataTables to defer the creation of the table elements for + * each row until they are needed for a draw - saving a significant amount of + * time. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/arrays.txt", + * "bDeferRender": true + * } ); + * } ); + */ + "bDeferRender": false, + + + /** + * Replace a DataTable which matches the given selector and replace it with + * one which has the properties of the new initialisation object passed. If no + * table matches the selector, then the new DataTable will be constructed as + * per normal. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * // Some time later.... + * $('#example').dataTable( { + * "bFilter": false, + * "bDestroy": true + * } ); + * } ); + */ + "bDestroy": false, + + + /** + * Enable or disable filtering of data. Filtering in DataTables is "smart" in + * that it allows the end user to input multiple words (space separated) and + * will match a row containing those words, even if not in the order that was + * specified (this allow matching across multiple columns). Note that if you + * wish to use filtering in DataTables this must remain 'true' - to remove the + * default filtering input box and retain filtering abilities, please use + * {@link DataTable.defaults.sDom}. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bFilter": false + * } ); + * } ); + */ + "bFilter": true, + + + /** + * Enable or disable the table information display. This shows information + * about the data that is currently visible on the page, including information + * about filtered data if that action is being performed. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bInfo": false + * } ); + * } ); + */ + "bInfo": true, + + + /** + * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some + * slightly different and additional mark-up from what DataTables has + * traditionally used). + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bJQueryUI": true + * } ); + * } ); + */ + "bJQueryUI": false, + + + /** + * Allows the end user to select the size of a formatted page from a select + * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate). + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bLengthChange": false + * } ); + * } ); + */ + "bLengthChange": true, + + + /** + * Enable or disable pagination. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bPaginate": false + * } ); + * } ); + */ + "bPaginate": true, + + + /** + * Enable or disable the display of a 'processing' indicator when the table is + * being processed (e.g. a sort). This is particularly useful for tables with + * large amounts of data where it can take a noticeable amount of time to sort + * the entries. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bProcessing": true + * } ); + * } ); + */ + "bProcessing": false, + + + /** + * Retrieve the DataTables object for the given selector. Note that if the + * table has already been initialised, this parameter will cause DataTables + * to simply return the object that has already been set up - it will not take + * account of any changes you might have made to the initialisation object + * passed to DataTables (setting this parameter to true is an acknowledgement + * that you understand this). bDestroy can be used to reinitialise a table if + * you need. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * initTable(); + * tableActions(); + * } ); + * + * function initTable () + * { + * return $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false, + * "bRetrieve": true + * } ); + * } + * + * function tableActions () + * { + * var oTable = initTable(); + * // perform API operations with oTable + * } + */ + "bRetrieve": false, + + + /** + * Indicate if DataTables should be allowed to set the padding / margin + * etc for the scrolling header elements or not. Typically you will want + * this. + * @type boolean + * @default true + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollAutoCss": false, + * "sScrollY": "200px" + * } ); + * } ); + */ + "bScrollAutoCss": true, + + + /** + * When vertical (y) scrolling is enabled, DataTables will force the height of + * the table's viewport to the given height at all times (useful for layout). + * However, this can look odd when filtering data down to a small data set, + * and the footer is left "floating" further down. This parameter (when + * enabled) will cause DataTables to collapse the table's viewport down when + * the result set will fit within the given Y height. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200", + * "bScrollCollapse": true + * } ); + * } ); + */ + "bScrollCollapse": false, + + + /** + * Enable infinite scrolling for DataTables (to be used in combination with + * sScrollY). Infinite scrolling means that DataTables will continually load + * data as a user scrolls through a table, which is very useful for large + * dataset. This cannot be used with pagination, which is automatically + * disabled. Note - the Scroller extra for DataTables is recommended in + * in preference to this option. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollInfinite": true, + * "bScrollCollapse": true, + * "sScrollY": "200px" + * } ); + * } ); + */ + "bScrollInfinite": false, + + + /** + * Configure DataTables to use server-side processing. Note that the + * sAjaxSource parameter must also be given in order to give DataTables a + * source to obtain the required data for each draw. + * @type boolean + * @default false + * @dtopt Features + * @dtopt Server-side + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "xhr.php" + * } ); + * } ); + */ + "bServerSide": false, + + + /** + * Enable or disable sorting of columns. Sorting of individual columns can be + * disabled by the "bSortable" option for each column. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bSort": false + * } ); + * } ); + */ + "bSort": true, + + + /** + * Allows control over whether DataTables should use the top (true) unique + * cell that is found for a single column, or the bottom (false - default). + * This is useful when using complex headers. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bSortCellsTop": true + * } ); + * } ); + */ + "bSortCellsTop": false, + + + /** + * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and + * 'sorting_3' to the columns which are currently being sorted on. This is + * presented as a feature switch as it can increase processing time (while + * classes are removed and added) so for large data sets you might want to + * turn this off. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bSortClasses": false + * } ); + * } ); + */ + "bSortClasses": true, + + + /** + * Enable or disable state saving. When enabled a cookie will be used to save + * table display information such as pagination information, display length, + * filtering and sorting. As such when the end user reloads the page the + * display display will match what thy had previously set up. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bStateSave": true + * } ); + * } ); + */ + "bStateSave": false, + + + /** + * Customise the cookie and / or the parameters being stored when using + * DataTables with state saving enabled. This function is called whenever + * the cookie is modified, and it expects a fully formed cookie string to be + * returned. Note that the data object passed in is a Javascript object which + * must be converted to a string (JSON.stringify for example). + * @type function + * @param {string} sName Name of the cookie defined by DataTables + * @param {object} oData Data to be stored in the cookie + * @param {string} sExpires Cookie expires string + * @param {string} sPath Path of the cookie to set + * @returns {string} Cookie formatted string (which should be encoded by + * using encodeURIComponent()) + * @dtopt Callbacks + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "fnCookieCallback": function (sName, oData, sExpires, sPath) { + * // Customise oData or sName or whatever else here + * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath; + * } + * } ); + * } ); + */ + "fnCookieCallback": null, + + + /** + * This function is called when a TR element is created (and all TD child + * elements have been inserted), or registered if using a DOM source, allowing + * manipulation of the TR element (adding classes etc). + * @type function + * @param {node} nRow "TR" element for the current row + * @param {array} aData Raw data array for this row + * @param {int} iDataIndex The index of this row in aoData + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnCreatedRow": function( nRow, aData, iDataIndex ) { + * // Bold the grade for all 'A' grade browsers + * if ( aData[4] == "A" ) + * { + * $('td:eq(4)', nRow).html( 'A' ); + * } + * } + * } ); + * } ); + */ + "fnCreatedRow": null, + + + /** + * This function is called on every 'draw' event, and allows you to + * dynamically modify any aspect you want about the created DOM. + * @type function + * @param {object} oSettings DataTables settings object + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnDrawCallback": function( oSettings ) { + * alert( 'DataTables has redrawn the table' ); + * } + * } ); + * } ); + */ + "fnDrawCallback": null, + + + /** + * Identical to fnHeaderCallback() but for the table footer this function + * allows you to modify the table footer on every 'draw' even. + * @type function + * @param {node} nFoot "TR" element for the footer + * @param {array} aData Full table data (as derived from the original HTML) + * @param {int} iStart Index for the current display starting point in the + * display array + * @param {int} iEnd Index for the current display ending point in the + * display array + * @param {array int} aiDisplay Index array to translate the visual position + * to the full data array + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) { + * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart; + * } + * } ); + * } ) + */ + "fnFooterCallback": null, + + + /** + * When rendering large numbers in the information element for the table + * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers + * to have a comma separator for the 'thousands' units (e.g. 1 million is + * rendered as "1,000,000") to help readability for the end user. This + * function will override the default method DataTables uses. + * @type function + * @member + * @param {int} iIn number to be formatted + * @returns {string} formatted string for DataTables to show the number + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnFormatNumber": function ( iIn ) { + * if ( iIn < 1000 ) { + * return iIn; + * } else { + * var + * s=(iIn+""), + * a=s.split(""), out="", + * iLen=s.length; + * + * for ( var i=0 ; i<iLen ; i++ ) { + * if ( i%3 === 0 && i !== 0 ) { + * out = "'"+out; + * } + * out = a[iLen-i-1]+out; + * } + * } + * return out; + * }; + * } ); + * } ); + */ + "fnFormatNumber": function ( iIn ) { + if ( iIn < 1000 ) + { + // A small optimisation for what is likely to be the majority of use cases + return iIn; + } + + var s=(iIn+""), a=s.split(""), out="", iLen=s.length; + + for ( var i=0 ; iA
    ' ); + * } + * } + * } ); + * } ); + */ + "fnRowCallback": null, + + + /** + * This parameter allows you to override the default function which obtains + * the data from the server ($.getJSON) so something more suitable for your + * application. For example you could use POST data, or pull information from + * a Gears or AIR database. + * @type function + * @member + * @param {string} sSource HTTP source to obtain the data from (sAjaxSource) + * @param {array} aoData A key/value pair object containing the data to send + * to the server + * @param {function} fnCallback to be called on completion of the data get + * process that will draw the data on the page. + * @param {object} oSettings DataTables settings object + * @dtopt Callbacks + * @dtopt Server-side + * + * @example + * // POST data to server + * $(document).ready( function() { + * $('#example').dataTable( { + * "bProcessing": true, + * "bServerSide": true, + * "sAjaxSource": "xhr.php", + * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) { + * oSettings.jqXHR = $.ajax( { + * "dataType": 'json', + * "type": "POST", + * "url": sSource, + * "data": aoData, + * "success": fnCallback + * } ); + * } + * } ); + * } ); + */ + "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) { + oSettings.jqXHR = $.ajax( { + "url": sUrl, + "data": aoData, + "success": function (json) { + if ( json.sError ) { + oSettings.oApi._fnLog( oSettings, 0, json.sError ); + } + + $(oSettings.oInstance).trigger('xhr', [oSettings, json]); + fnCallback( json ); + }, + "dataType": "json", + "cache": false, + "type": oSettings.sServerMethod, + "error": function (xhr, error, thrown) { + if ( error == "parsererror" ) { + oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+ + "server could not be parsed. This is caused by a JSON formatting error." ); + } + } + } ); + }, + + + /** + * It is often useful to send extra data to the server when making an Ajax + * request - for example custom filtering information, and this callback + * function makes it trivial to send extra information to the server. The + * passed in parameter is the data set that has been constructed by + * DataTables, and you can add to this or modify it as you require. + * @type function + * @param {array} aoData Data array (array of objects which are name/value + * pairs) that has been constructed by DataTables and will be sent to the + * server. In the case of Ajax sourced data with server-side processing + * this will be an empty array, for server-side processing there will be a + * significant number of parameters! + * @returns {undefined} Ensure that you modify the aoData array passed in, + * as this is passed by reference. + * @dtopt Callbacks + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bProcessing": true, + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "fnServerParams": function ( aoData ) { + * aoData.push( { "name": "more_data", "value": "my_value" } ); + * } + * } ); + * } ); + */ + "fnServerParams": null, + + + /** + * Load the table state. With this function you can define from where, and how, the + * state of a table is loaded. By default DataTables will load from its state saving + * cookie, but you might wish to use local storage (HTML5) or a server-side database. + * @type function + * @member + * @param {object} oSettings DataTables settings object + * @return {object} The DataTables state object to be loaded + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoad": function (oSettings) { + * var o; + * + * // Send an Ajax request to the server to get the data. Note that + * // this is a synchronous request. + * $.ajax( { + * "url": "/state_load", + * "async": false, + * "dataType": "json", + * "success": function (json) { + * o = json; + * } + * } ); + * + * return o; + * } + * } ); + * } ); + */ + "fnStateLoad": function ( oSettings ) { + var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance ); + var oData; + + try { + oData = (typeof $.parseJSON === 'function') ? + $.parseJSON(sData) : eval( '('+sData+')' ); + } catch (e) { + oData = null; + } + + return oData; + }, + + + /** + * Callback which allows modification of the saved state prior to loading that state. + * This callback is called when the table is loading state from the stored data, but + * prior to the settings object being modified by the saved state. Note that for + * plug-in authors, you should use the 'stateLoadParams' event to load parameters for + * a plug-in. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object that is to be loaded + * @dtopt Callbacks + * + * @example + * // Remove a saved filter, so filtering is never loaded + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoadParams": function (oSettings, oData) { + * oData.oSearch.sSearch = ""; + * } + * } ); + * } ); + * + * @example + * // Disallow state loading by returning false + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoadParams": function (oSettings, oData) { + * return false; + * } + * } ); + * } ); + */ + "fnStateLoadParams": null, + + + /** + * Callback that is called when the state has been loaded from the state saving method + * and the DataTables settings object has been modified as a result of the loaded state. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object that was loaded + * @dtopt Callbacks + * + * @example + * // Show an alert with the filtering value that was saved + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoaded": function (oSettings, oData) { + * alert( 'Saved filter was: '+oData.oSearch.sSearch ); + * } + * } ); + * } ); + */ + "fnStateLoaded": null, + + + /** + * Save the table state. This function allows you to define where and how the state + * information for the table is stored - by default it will use a cookie, but you + * might want to use local storage (HTML5) or a server-side database. + * @type function + * @member + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object to be saved + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateSave": function (oSettings, oData) { + * // Send an Ajax request to the server with the state object + * $.ajax( { + * "url": "/state_save", + * "data": oData, + * "dataType": "json", + * "method": "POST" + * "success": function () {} + * } ); + * } + * } ); + * } ); + */ + "fnStateSave": function ( oSettings, oData ) { + this.oApi._fnCreateCookie( + oSettings.sCookiePrefix+oSettings.sInstance, + this.oApi._fnJsonString(oData), + oSettings.iCookieDuration, + oSettings.sCookiePrefix, + oSettings.fnCookieCallback + ); + }, + + + /** + * Callback which allows modification of the state to be saved. Called when the table + * has changed state a new state save is required. This method allows modification of + * the state saving object prior to actually doing the save, including addition or + * other state properties or modification. Note that for plug-in authors, you should + * use the 'stateSaveParams' event to save parameters for a plug-in. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object to be saved + * @dtopt Callbacks + * + * @example + * // Remove a saved filter, so filtering is never saved + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateSaveParams": function (oSettings, oData) { + * oData.oSearch.sSearch = ""; + * } + * } ); + * } ); + */ + "fnStateSaveParams": null, + + + /** + * Duration of the cookie which is used for storing session information. This + * value is given in seconds. + * @type int + * @default 7200 (2 hours) + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iCookieDuration": 60*60*24; // 1 day + * } ); + * } ) + */ + "iCookieDuration": 7200, + + + /** + * When enabled DataTables will not make a request to the server for the first + * page draw - rather it will use the data already on the page (no sorting etc + * will be applied to it), thus saving on an XHR at load time. iDeferLoading + * is used to indicate that deferred loading is required, but it is also used + * to tell DataTables how many records there are in the full table (allowing + * the information element and pagination to be displayed correctly). In the case + * where a filtering is applied to the table on initial load, this can be + * indicated by giving the parameter as an array, where the first element is + * the number of records available after filtering and the second element is the + * number of records without filtering (allowing the table information element + * to be shown correctly). + * @type int | array + * @default null + * @dtopt Options + * + * @example + * // 57 records available in the table, no filtering applied + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "iDeferLoading": 57 + * } ); + * } ); + * + * @example + * // 57 records after filtering, 100 without filtering (an initial filter applied) + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "iDeferLoading": [ 57, 100 ], + * "oSearch": { + * "sSearch": "my_filter" + * } + * } ); + * } ); + */ + "iDeferLoading": null, + + + /** + * Number of rows to display on a single page when using pagination. If + * feature enabled (bLengthChange) then the end user will be able to override + * this to a custom setting using a pop-up menu. + * @type int + * @default 10 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayLength": 50 + * } ); + * } ) + */ + "iDisplayLength": 10, + + + /** + * Define the starting point for data display when using DataTables with + * pagination. Note that this parameter is the number of records, rather than + * the page number, so if you have 10 records per page and want to start on + * the third page, it should be "20". + * @type int + * @default 0 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayStart": 20 + * } ); + * } ) + */ + "iDisplayStart": 0, + + + /** + * The scroll gap is the amount of scrolling that is left to go before + * DataTables will load the next 'page' of data automatically. You typically + * want a gap which is big enough that the scrolling will be smooth for the + * user, while not so large that it will load more data than need. + * @type int + * @default 100 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollInfinite": true, + * "bScrollCollapse": true, + * "sScrollY": "200px", + * "iScrollLoadGap": 50 + * } ); + * } ); + */ + "iScrollLoadGap": 100, + + + /** + * By default DataTables allows keyboard navigation of the table (sorting, paging, + * and filtering) by adding a tabindex attribute to the required elements. This + * allows you to tab through the controls and press the enter key to activate them. + * The tabindex is default 0, meaning that the tab follows the flow of the document. + * You can overrule this using this parameter if you wish. Use a value of -1 to + * disable built-in keyboard navigation. + * @type int + * @default 0 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iTabIndex": 1 + * } ); + * } ); + */ + "iTabIndex": 0, + + + /** + * All strings that DataTables uses in the user interface that it creates + * are defined in this object, allowing you to modified them individually or + * completely replace them all as required. + * @namespace + */ + "oLanguage": { + /** + * Strings that are used for WAI-ARIA labels and controls only (these are not + * actually visible on the page, but will be read by screenreaders, and thus + * must be internationalised as well). + * @namespace + */ + "oAria": { + /** + * ARIA label that is added to the table headers when the column may be + * sorted ascending by activing the column (click or return when focused). + * Note that the column header is prefixed to this string. + * @type string + * @default : activate to sort column ascending + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oAria": { + * "sSortAscending": " - click/return to sort ascending" + * } + * } + * } ); + * } ); + */ + "sSortAscending": ": activate to sort column ascending", + + /** + * ARIA label that is added to the table headers when the column may be + * sorted descending by activing the column (click or return when focused). + * Note that the column header is prefixed to this string. + * @type string + * @default : activate to sort column ascending + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oAria": { + * "sSortDescending": " - click/return to sort descending" + * } + * } + * } ); + * } ); + */ + "sSortDescending": ": activate to sort column descending" + }, + + /** + * Pagination string used by DataTables for the two built-in pagination + * control types ("two_button" and "full_numbers") + * @namespace + */ + "oPaginate": { + /** + * Text to use when using the 'full_numbers' type of pagination for the + * button to take the user to the first page. + * @type string + * @default First + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sFirst": "First page" + * } + * } + * } ); + * } ); + */ + "sFirst": "First", + + + /** + * Text to use when using the 'full_numbers' type of pagination for the + * button to take the user to the last page. + * @type string + * @default Last + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sLast": "Last page" + * } + * } + * } ); + * } ); + */ + "sLast": "Last", + + + /** + * Text to use for the 'next' pagination button (to take the user to the + * next page). + * @type string + * @default Next + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sNext": "Next page" + * } + * } + * } ); + * } ); + */ + "sNext": "Next", + + + /** + * Text to use for the 'previous' pagination button (to take the user to + * the previous page). + * @type string + * @default Previous + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sPrevious": "Previous page" + * } + * } + * } ); + * } ); + */ + "sPrevious": "Previous" + }, + + /** + * This string is shown in preference to sZeroRecords when the table is + * empty of data (regardless of filtering). Note that this is an optional + * parameter - if it is not given, the value of sZeroRecords will be used + * instead (either the default or given value). + * @type string + * @default No data available in table + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sEmptyTable": "No data available in table" + * } + * } ); + * } ); + */ + "sEmptyTable": "No data available in table", + + + /** + * This string gives information to the end user about the information that + * is current on display on the page. The _START_, _END_ and _TOTAL_ + * variables are all dynamically replaced as the table display updates, and + * can be freely moved or removed as the language requirements change. + * @type string + * @default Showing _START_ to _END_ of _TOTAL_ entries + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)" + * } + * } ); + * } ); + */ + "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", + + + /** + * Display information string for when the table is empty. Typically the + * format of this string should match sInfo. + * @type string + * @default Showing 0 to 0 of 0 entries + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoEmpty": "No entries to show" + * } + * } ); + * } ); + */ + "sInfoEmpty": "Showing 0 to 0 of 0 entries", + + + /** + * When a user filters the information in a table, this string is appended + * to the information (sInfo) to give an idea of how strong the filtering + * is. The variable _MAX_ is dynamically updated. + * @type string + * @default (filtered from _MAX_ total entries) + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoFiltered": " - filtering from _MAX_ records" + * } + * } ); + * } ); + */ + "sInfoFiltered": "(filtered from _MAX_ total entries)", + + + /** + * If can be useful to append extra information to the info string at times, + * and this variable does exactly that. This information will be appended to + * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are + * being used) at all times. + * @type string + * @default Empty string + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoPostFix": "All records shown are derived from real information." + * } + * } ); + * } ); + */ + "sInfoPostFix": "", + + + /** + * DataTables has a build in number formatter (fnFormatNumber) which is used + * to format large numbers that are used in the table information. By + * default a comma is used, but this can be trivially changed to any + * character you wish with this parameter. + * @type string + * @default , + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoThousands": "'" + * } + * } ); + * } ); + */ + "sInfoThousands": ",", + + + /** + * Detail the action that will be taken when the drop down menu for the + * pagination length option is changed. The '_MENU_' variable is replaced + * with a default select list of 10, 25, 50 and 100, and can be replaced + * with a custom select box if required. + * @type string + * @default Show _MENU_ entries + * @dtopt Language + * + * @example + * // Language change only + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLengthMenu": "Display _MENU_ records" + * } + * } ); + * } ); + * + * @example + * // Language and options change + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLengthMenu": 'Display records' + * } + * } ); + * } ); + */ + "sLengthMenu": "Show _MENU_ entries", + + + /** + * When using Ajax sourced data and during the first draw when DataTables is + * gathering the data, this message is shown in an empty row in the table to + * indicate to the end user the the data is being loaded. Note that this + * parameter is not used when loading data by server-side processing, just + * Ajax sourced data with client-side processing. + * @type string + * @default Loading... + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLoadingRecords": "Please wait - loading..." + * } + * } ); + * } ); + */ + "sLoadingRecords": "Loading...", + + + /** + * Text which is displayed when the table is processing a user action + * (usually a sort command or similar). + * @type string + * @default Processing... + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sProcessing": "DataTables is currently busy" + * } + * } ); + * } ); + */ + "sProcessing": "Processing...", + + + /** + * Details the actions that will be taken when the user types into the + * filtering input text box. The variable "_INPUT_", if used in the string, + * is replaced with the HTML text box for the filtering input allowing + * control over where it appears in the string. If "_INPUT_" is not given + * then the input box is appended to the string automatically. + * @type string + * @default Search: + * @dtopt Language + * + * @example + * // Input text box will be appended at the end automatically + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sSearch": "Filter records:" + * } + * } ); + * } ); + * + * @example + * // Specify where the filter should appear + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sSearch": "Apply filter _INPUT_ to table" + * } + * } ); + * } ); + */ + "sSearch": "Search:", + + + /** + * All of the language information can be stored in a file on the + * server-side, which DataTables will look up if this parameter is passed. + * It must store the URL of the language file, which is in a JSON format, + * and the object has the same properties as the oLanguage object in the + * initialiser object (i.e. the above parameters). Please refer to one of + * the example language files to see how this works in action. + * @type string + * @default Empty string - i.e. disabled + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt" + * } + * } ); + * } ); + */ + "sUrl": "", + + + /** + * Text shown inside the table records when the is no information to be + * displayed after filtering. sEmptyTable is shown when there is simply no + * information in the table at all (regardless of filtering). + * @type string + * @default No matching records found + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sZeroRecords": "No records to display" + * } + * } ); + * } ); + */ + "sZeroRecords": "No matching records found" + }, + + + /** + * This parameter allows you to have define the global filtering state at + * initialisation time. As an object the "sSearch" parameter must be + * defined, but all other parameters are optional. When "bRegex" is true, + * the search string will be treated as a regular expression, when false + * (default) it will be treated as a straight string. When "bSmart" + * DataTables will use it's smart filtering methods (to word match at + * any point in the data), when false this will not be done. + * @namespace + * @extends DataTable.models.oSearch + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oSearch": {"sSearch": "Initial search"} + * } ); + * } ) + */ + "oSearch": $.extend( {}, DataTable.models.oSearch ), + + + /** + * By default DataTables will look for the property 'aaData' when obtaining + * data from an Ajax source or for server-side processing - this parameter + * allows that property to be changed. You can use Javascript dotted object + * notation to get a data source for multiple levels of nesting. + * @type string + * @default aaData + * @dtopt Options + * @dtopt Server-side + * + * @example + * // Get data from { "data": [...] } + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/data.txt", + * "sAjaxDataProp": "data" + * } ); + * } ); + * + * @example + * // Get data from { "data": { "inner": [...] } } + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/data.txt", + * "sAjaxDataProp": "data.inner" + * } ); + * } ); + */ + "sAjaxDataProp": "aaData", + + + /** + * You can instruct DataTables to load data from an external source using this + * parameter (use aData if you want to pass data in you already have). Simply + * provide a url a JSON object can be obtained from. This object must include + * the parameter 'aaData' which is the data source for the table. + * @type string + * @default null + * @dtopt Options + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php" + * } ); + * } ) + */ + "sAjaxSource": null, + + + /** + * This parameter can be used to override the default prefix that DataTables + * assigns to a cookie when state saving is enabled. + * @type string + * @default SpryMedia_DataTables_ + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sCookiePrefix": "my_datatable_", + * } ); + * } ); + */ + "sCookiePrefix": "SpryMedia_DataTables_", + + + /** + * This initialisation variable allows you to specify exactly where in the + * DOM you want DataTables to inject the various controls it adds to the page + * (for example you might want the pagination controls at the top of the + * table). DIV elements (with or without a custom class) can also be added to + * aid styling. The follow syntax is used: + *
      + *
    • The following options are allowed: + *
        + *
      • 'l' - Length changing
      • 'f' - Filtering input + *
      • 't' - The table!
      • + *
      • 'i' - Information
      • + *
      • 'p' - Pagination
      • + *
      • 'r' - pRocessing
      • + *
      + *
    • + *
    • The following constants are allowed: + *
        + *
      • 'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')
      • + *
      • 'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')
      • + *
      + *
    • + *
    • The following syntax is expected: + *
        + *
      • '<' and '>' - div elements
      • + *
      • '<"class" and '>' - div with a class
      • + *
      • '<"#id" and '>' - div with an ID
      • + *
      + *
    • + *
    • Examples: + *
        + *
      • '<"wrapper"flipt>'
      • + *
      • '<lf<t>ip>'
      • + *
      + *
    • + *
    + * @type string + * @default lfrtip (when bJQueryUI is false) or + * <"H"lfr>t<"F"ip> (when bJQueryUI is true) + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sDom": '<"top"i>rt<"bottom"flp><"clear">' + * } ); + * } ); + */ + "sDom": "lfrtip", + + + /** + * DataTables features two different built-in pagination interaction methods + * ('two_button' or 'full_numbers') which present different page controls to + * the end user. Further methods can be added using the API (see below). + * @type string + * @default two_button + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sPaginationType": "full_numbers" + * } ); + * } ) + */ + "sPaginationType": "two_button", + + + /** + * Enable horizontal scrolling. When a table is too wide to fit into a certain + * layout, or you have a large number of columns in the table, you can enable + * x-scrolling to show the table in a viewport, which can be scrolled. This + * property can be any CSS unit, or a number (in which case it will be treated + * as a pixel measurement). + * @type string + * @default blank string - i.e. disabled + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollX": "100%", + * "bScrollCollapse": true + * } ); + * } ); + */ + "sScrollX": "", + + + /** + * This property can be used to force a DataTable to use more width than it + * might otherwise do when x-scrolling is enabled. For example if you have a + * table which requires to be well spaced, this parameter is useful for + * "over-sizing" the table, and thus forcing scrolling. This property can by + * any CSS unit, or a number (in which case it will be treated as a pixel + * measurement). + * @type string + * @default blank string - i.e. disabled + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollX": "100%", + * "sScrollXInner": "110%" + * } ); + * } ); + */ + "sScrollXInner": "", + + + /** + * Enable vertical scrolling. Vertical scrolling will constrain the DataTable + * to the given height, and enable scrolling for any data which overflows the + * current viewport. This can be used as an alternative to paging to display + * a lot of data in a small area (although paging and scrolling can both be + * enabled at the same time). This property can be any CSS unit, or a number + * (in which case it will be treated as a pixel measurement). + * @type string + * @default blank string - i.e. disabled + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * } ); + */ + "sScrollY": "", + + + /** + * Set the HTTP method that is used to make the Ajax call for server-side + * processing or Ajax sourced data. + * @type string + * @default GET + * @dtopt Options + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/post.php", + * "sServerMethod": "POST" + * } ); + * } ); + */ + "sServerMethod": "GET" + }; + + + + /** + * Column options that can be given to DataTables at initialisation time. + * @namespace + */ + DataTable.defaults.columns = { + /** + * Allows a column's sorting to take multiple columns into account when + * doing a sort. For example first name / last name columns make sense to + * do a multi-column sort over the two columns. + * @type array + * @default null Takes the value of the column index automatically + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] }, + * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] }, + * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "aDataSort": [ 0, 1 ] }, + * { "aDataSort": [ 1, 0 ] }, + * { "aDataSort": [ 2, 3, 4 ] }, + * null, + * null + * ] + * } ); + * } ); + */ + "aDataSort": null, + + + /** + * You can control the default sorting direction, and even alter the behaviour + * of the sort handler (i.e. only allow ascending sorting etc) using this + * parameter. + * @type array + * @default [ 'asc', 'desc' ] + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "asSorting": [ "asc" ], "aTargets": [ 1 ] }, + * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] }, + * { "asSorting": [ "desc" ], "aTargets": [ 3 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * { "asSorting": [ "asc" ] }, + * { "asSorting": [ "desc", "asc", "asc" ] }, + * { "asSorting": [ "desc" ] }, + * null + * ] + * } ); + * } ); + */ + "asSorting": [ 'asc', 'desc' ], + + + /** + * Enable or disable filtering on the data in this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bSearchable": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bSearchable": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bSearchable": true, + + + /** + * Enable or disable sorting on this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bSortable": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bSortable": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bSortable": true, + + + /** + * Deprecated When using fnRender() for a column, you may wish + * to use the original data (before rendering) for sorting and filtering + * (the default is to used the rendered data that the user can see). This + * may be useful for dates etc. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type boolean + * @default true + * @dtopt Columns + * @deprecated + */ + "bUseRendered": true, + + + /** + * Enable or disable the display of this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bVisible": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bVisible": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bVisible": true, + + + /** + * Developer definable function that is called whenever a cell is created (Ajax source, + * etc) or processed for input (DOM source). This can be used as a compliment to mRender + * allowing you to modify the DOM element (add background colour for example) when the + * element is available. + * @type function + * @param {element} nTd The TD node that has been created + * @param {*} sData The Data for the cell + * @param {array|object} oData The data for the whole row + * @param {int} iRow The row index for the aoData data store + * @param {int} iCol The column index for aoColumns + * @dtopt Columns + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [3], + * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) { + * if ( sData == "1.7" ) { + * $(nTd).css('color', 'blue') + * } + * } + * } ] + * }); + * } ); + */ + "fnCreatedCell": null, + + + /** + * Deprecated Custom display function that will be called for the + * display of each cell in this column. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type function + * @param {object} o Object with the following parameters: + * @param {int} o.iDataRow The row in aoData + * @param {int} o.iDataColumn The column in question + * @param {array} o.aData The data for the row in question + * @param {object} o.oSettings The settings object for this DataTables instance + * @param {object} o.mDataProp The data property used for this column + * @param {*} val The current cell value + * @returns {string} The string you which to use in the display + * @dtopt Columns + * @deprecated + */ + "fnRender": null, + + + /** + * The column index (starting from 0!) that you wish a sort to be performed + * upon when this column is selected for sorting. This can be used for sorting + * on hidden columns for example. + * @type int + * @default -1 Use automatically calculated column index + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "iDataSort": 1, "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "iDataSort": 1 }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "iDataSort": -1, + + + /** + * This parameter has been replaced by mData in DataTables to ensure naming + * consistency. mDataProp can still be used, as there is backwards compatibility + * in DataTables for this option, but it is strongly recommended that you use + * mData in preference to mDataProp. + * @name DataTable.defaults.columns.mDataProp + */ + + + /** + * This property can be used to read data from any JSON data source property, + * including deeply nested objects / properties. mData can be given in a + * number of different ways which effect its behaviour: + *
      + *
    • integer - treated as an array index for the data source. This is the + * default that DataTables uses (incrementally increased for each column).
    • + *
    • string - read an object property from the data source. Note that you can + * use Javascript dotted notation to read deep properties / arrays from the + * data source.
    • + *
    • null - the sDefaultContent option will be used for the cell (null + * by default, so you will need to specify the default content you want - + * typically an empty string). This can be useful on generated columns such + * as edit / delete action columns.
    • + *
    • function - the function given will be executed whenever DataTables + * needs to set or get the data for a cell in the column. The function + * takes three parameters: + *
        + *
      • {array|object} The data source for the row
      • + *
      • {string} The type call data requested - this will be 'set' when + * setting data or 'filter', 'display', 'type', 'sort' or undefined when + * gathering data. Note that when undefined is given for the type + * DataTables expects to get the raw data for the object back
      • + *
      • {*} Data to set when the second parameter is 'set'.
      • + *
      + * The return value from the function is not required when 'set' is the type + * of call, but otherwise the return is what will be used for the data + * requested.
    • + *
    + * + * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change + * reflects the flexibility of this property and is consistent with the naming of + * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as + * it automatically maps the old name to the new if required. + * @type string|int|function|null + * @default null Use automatically calculated column index + * @dtopt Columns + * + * @example + * // Read table data from objects + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/deep.txt", + * "aoColumns": [ + * { "mData": "engine" }, + * { "mData": "browser" }, + * { "mData": "platform.inner" }, + * { "mData": "platform.details.0" }, + * { "mData": "platform.details.1" } + * ] + * } ); + * } ); + * + * @example + * // Using mData as a function to provide different information for + * // sorting, filtering and display. In this case, currency (price) + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [ 0 ], + * "mData": function ( source, type, val ) { + * if (type === 'set') { + * source.price = val; + * // Store the computed dislay and filter values for efficiency + * source.price_display = val=="" ? "" : "$"+numberFormat(val); + * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; + * return; + * } + * else if (type === 'display') { + * return source.price_display; + * } + * else if (type === 'filter') { + * return source.price_filter; + * } + * // 'sort', 'type' and undefined all just use the integer + * return source.price; + * } + * } ] + * } ); + * } ); + */ + "mData": null, + + + /** + * This property is the rendering partner to mData and it is suggested that + * when you want to manipulate data for display (including filtering, sorting etc) + * but not altering the underlying data for the table, use this property. mData + * can actually do everything this property can and more, but this parameter is + * easier to use since there is no 'set' option. Like mData is can be given + * in a number of different ways to effect its behaviour, with the addition of + * supporting array syntax for easy outputting of arrays (including arrays of + * objects): + *
      + *
    • integer - treated as an array index for the data source. This is the + * default that DataTables uses (incrementally increased for each column).
    • + *
    • string - read an object property from the data source. Note that you can + * use Javascript dotted notation to read deep properties / arrays from the + * data source and also array brackets to indicate that the data reader should + * loop over the data source array. When characters are given between the array + * brackets, these characters are used to join the data source array together. + * For example: "accounts[, ].name" would result in a comma separated list with + * the 'name' value from the 'accounts' array of objects.
    • + *
    • function - the function given will be executed whenever DataTables + * needs to set or get the data for a cell in the column. The function + * takes three parameters: + *
        + *
      • {array|object} The data source for the row (based on mData)
      • + *
      • {string} The type call data requested - this will be 'filter', 'display', + * 'type' or 'sort'.
      • + *
      • {array|object} The full data source for the row (not based on mData)
      • + *
      + * The return value from the function is what will be used for the data + * requested.
    • + *
    + * @type string|int|function|null + * @default null Use mData + * @dtopt Columns + * + * @example + * // Create a comma separated list from an array of objects + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/deep.txt", + * "aoColumns": [ + * { "mData": "engine" }, + * { "mData": "browser" }, + * { + * "mData": "platform", + * "mRender": "[, ].name" + * } + * ] + * } ); + * } ); + * + * @example + * // Use as a function to create a link from the data source + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ + * { + * "aTargets": [ 0 ], + * "mData": "download_link", + * "mRender": function ( data, type, full ) { + * return 'Download'; + * } + * ] + * } ); + * } ); + */ + "mRender": null, + + + /** + * Change the cell type created for the column - either TD cells or TH cells. This + * can be useful as TH cells have semantic meaning in the table body, allowing them + * to act as a header for a row (you may wish to add scope='row' to the TH elements). + * @type string + * @default td + * @dtopt Columns + * + * @example + * // Make the first column use TH cells + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [ 0 ], + * "sCellType": "th" + * } ] + * } ); + * } ); + */ + "sCellType": "td", + + + /** + * Class to give to each cell in this column. + * @type string + * @default Empty string + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sClass": "my_class", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sClass": "my_class" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sClass": "", + + /** + * When DataTables calculates the column widths to assign to each column, + * it finds the longest string in each column and then constructs a + * temporary table and reads the widths from that. The problem with this + * is that "mmm" is much wider then "iiii", but the latter is a longer + * string - thus the calculation can go wrong (doing it properly and putting + * it into an DOM object and measuring that is horribly(!) slow). Thus as + * a "work around" we provide this option. It will append its value to the + * text that is found to be the longest string for the column - i.e. padding. + * Generally you shouldn't need this, and it is not documented on the + * general DataTables.net documentation + * @type string + * @default Empty string + * @dtopt Columns + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * null, + * { + * "sContentPadding": "mmm" + * } + * ] + * } ); + * } ); + */ + "sContentPadding": "", + + + /** + * Allows a default value to be given for a column's data, and will be used + * whenever a null data source is encountered (this can be because mData + * is set to null, or because the data source itself is null). + * @type string + * @default null + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { + * "mData": null, + * "sDefaultContent": "Edit", + * "aTargets": [ -1 ] + * } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * null, + * { + * "mData": null, + * "sDefaultContent": "Edit" + * } + * ] + * } ); + * } ); + */ + "sDefaultContent": null, + + + /** + * This parameter is only used in DataTables' server-side processing. It can + * be exceptionally useful to know what columns are being displayed on the + * client side, and to map these to database fields. When defined, the names + * also allow DataTables to reorder information from the server if it comes + * back in an unexpected order (i.e. if you switch your columns around on the + * client-side, your server-side code does not also need updating). + * @type string + * @default Empty string + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sName": "engine", "aTargets": [ 0 ] }, + * { "sName": "browser", "aTargets": [ 1 ] }, + * { "sName": "platform", "aTargets": [ 2 ] }, + * { "sName": "version", "aTargets": [ 3 ] }, + * { "sName": "grade", "aTargets": [ 4 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sName": "engine" }, + * { "sName": "browser" }, + * { "sName": "platform" }, + * { "sName": "version" }, + * { "sName": "grade" } + * ] + * } ); + * } ); + */ + "sName": "", + + + /** + * Defines a data source type for the sorting which can be used to read + * real-time information from the table (updating the internally cached + * version) prior to sorting. This allows sorting to occur on user editable + * elements such as form inputs. + * @type string + * @default std + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] }, + * { "sType": "numeric", "aTargets": [ 3 ] }, + * { "sSortDataType": "dom-select", "aTargets": [ 4 ] }, + * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * { "sSortDataType": "dom-text" }, + * { "sSortDataType": "dom-text", "sType": "numeric" }, + * { "sSortDataType": "dom-select" }, + * { "sSortDataType": "dom-checkbox" } + * ] + * } ); + * } ); + */ + "sSortDataType": "std", + + + /** + * The title of this column. + * @type string + * @default null Derived from the 'TH' value for this column in the + * original HTML table. + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sTitle": "My column title", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sTitle": "My column title" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sTitle": null, + + + /** + * The type allows you to specify how the data for this column will be sorted. + * Four types (string, numeric, date and html (which will strip HTML tags + * before sorting)) are currently available. Note that only date formats + * understood by Javascript's Date() object will be accepted as type date. For + * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric', + * 'date' or 'html' (by default). Further types can be adding through + * plug-ins. + * @type string + * @default null Auto-detected from raw data + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sType": "html", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sType": "html" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sType": null, + + + /** + * Defining the width of the column, this parameter may take any CSS value + * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not + * been given a specific width through this interface ensuring that the table + * remains readable. + * @type string + * @default null Automatic + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sWidth": "20%", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sWidth": "20%" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sWidth": null + }; + + + + /** + * DataTables settings object - this holds all the information needed for a + * given table, including configuration, data and current application of the + * table options. DataTables does not have a single instance for each DataTable + * with the settings attached to that instance, but rather instances of the + * DataTable "class" are created on-the-fly as needed (typically by a + * $().dataTable() call) and the settings object is then applied to that + * instance. + * + * Note that this object is related to {@link DataTable.defaults} but this + * one is the internal data store for DataTables's cache of columns. It should + * NOT be manipulated outside of DataTables. Any configuration should be done + * through the initialisation options. + * @namespace + * @todo Really should attach the settings object to individual instances so we + * don't need to create new instances on each $().dataTable() call (if the + * table already exists). It would also save passing oSettings around and + * into every single function. However, this is a very significant + * architecture change for DataTables and will almost certainly break + * backwards compatibility with older installations. This is something that + * will be done in 2.0. + */ + DataTable.models.oSettings = { + /** + * Primary features of DataTables and their enablement state. + * @namespace + */ + "oFeatures": { + + /** + * Flag to say if DataTables should automatically try to calculate the + * optimum table and columns widths (true) or not (false). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bAutoWidth": null, + + /** + * Delay the creation of TR and TD elements until they are actually + * needed by a driven page draw. This can give a significant speed + * increase for Ajax source and Javascript source data, but makes no + * difference at all fro DOM and server-side processing tables. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bDeferRender": null, + + /** + * Enable filtering on the table or not. Note that if this is disabled + * then there is no filtering at all on the table, including fnFilter. + * To just remove the filtering input use sDom and remove the 'f' option. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bFilter": null, + + /** + * Table information element (the 'Showing x of y records' div) enable + * flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bInfo": null, + + /** + * Present a user control allowing the end user to change the page size + * when pagination is enabled. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bLengthChange": null, + + /** + * Pagination enabled or not. Note that if this is disabled then length + * changing must also be disabled. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bPaginate": null, + + /** + * Processing indicator enable flag whenever DataTables is enacting a + * user request - typically an Ajax request for server-side processing. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bProcessing": null, + + /** + * Server-side processing enabled flag - when enabled DataTables will + * get all data from the server for every draw - there is no filtering, + * sorting or paging done on the client-side. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bServerSide": null, + + /** + * Sorting enablement flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSort": null, + + /** + * Apply a class to the columns which are being sorted to provide a + * visual highlight or not. This can slow things down when enabled since + * there is a lot of DOM interaction. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSortClasses": null, + + /** + * State saving enablement flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bStateSave": null + }, + + + /** + * Scrolling settings for a table. + * @namespace + */ + "oScroll": { + /** + * Indicate if DataTables should be allowed to set the padding / margin + * etc for the scrolling header elements or not. Typically you will want + * this. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bAutoCss": null, + + /** + * When the table is shorter in height than sScrollY, collapse the + * table container down to the height of the table (when true). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bCollapse": null, + + /** + * Infinite scrolling enablement flag. Now deprecated in favour of + * using the Scroller plug-in. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bInfinite": null, + + /** + * Width of the scrollbar for the web-browser's platform. Calculated + * during table initialisation. + * @type int + * @default 0 + */ + "iBarWidth": 0, + + /** + * Space (in pixels) between the bottom of the scrolling container and + * the bottom of the scrolling viewport before the next page is loaded + * when using infinite scrolling. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type int + */ + "iLoadGap": null, + + /** + * Viewport width for horizontal scrolling. Horizontal scrolling is + * disabled if an empty string. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sX": null, + + /** + * Width to expand the table to when using x-scrolling. Typically you + * should not need to use this. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @deprecated + */ + "sXInner": null, + + /** + * Viewport height for vertical scrolling. Vertical scrolling is disabled + * if an empty string. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sY": null + }, + + /** + * Language information for the table. + * @namespace + * @extends DataTable.defaults.oLanguage + */ + "oLanguage": { + /** + * Information callback function. See + * {@link DataTable.defaults.fnInfoCallback} + * @type function + * @default null + */ + "fnInfoCallback": null + }, + + /** + * Browser support parameters + * @namespace + */ + "oBrowser": { + /** + * Indicate if the browser incorrectly calculates width:100% inside a + * scrolling element (IE6/7) + * @type boolean + * @default false + */ + "bScrollOversize": false + }, + + /** + * Array referencing the nodes which are used for the features. The + * parameters of this object match what is allowed by sDom - i.e. + *
      + *
    • 'l' - Length changing
    • + *
    • 'f' - Filtering input
    • + *
    • 't' - The table!
    • + *
    • 'i' - Information
    • + *
    • 'p' - Pagination
    • + *
    • 'r' - pRocessing
    • + *
    + * @type array + * @default [] + */ + "aanFeatures": [], + + /** + * Store data information - see {@link DataTable.models.oRow} for detailed + * information. + * @type array + * @default [] + */ + "aoData": [], + + /** + * Array of indexes which are in the current display (after filtering etc) + * @type array + * @default [] + */ + "aiDisplay": [], + + /** + * Array of indexes for display - no filtering + * @type array + * @default [] + */ + "aiDisplayMaster": [], + + /** + * Store information about each column that is in use + * @type array + * @default [] + */ + "aoColumns": [], + + /** + * Store information about the table's header + * @type array + * @default [] + */ + "aoHeader": [], + + /** + * Store information about the table's footer + * @type array + * @default [] + */ + "aoFooter": [], + + /** + * Search data array for regular expression searching + * @type array + * @default [] + */ + "asDataSearch": [], + + /** + * Store the applied global search information in case we want to force a + * research or compare the old search to a new one. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @namespace + * @extends DataTable.models.oSearch + */ + "oPreviousSearch": {}, + + /** + * Store the applied search for each column - see + * {@link DataTable.models.oSearch} for the format that is used for the + * filtering information for each column. + * @type array + * @default [] + */ + "aoPreSearchCols": [], + + /** + * Sorting that is applied to the table. Note that the inner arrays are + * used in the following manner: + *
      + *
    • Index 0 - column number
    • + *
    • Index 1 - current sorting direction
    • + *
    • Index 2 - index of asSorting for this column
    • + *
    + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @todo These inner arrays should really be objects + */ + "aaSorting": null, + + /** + * Sorting that is always applied to the table (i.e. prefixed in front of + * aaSorting). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array|null + * @default null + */ + "aaSortingFixed": null, + + /** + * Classes to use for the striping of a table. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @default [] + */ + "asStripeClasses": null, + + /** + * If restoring a table - we should restore its striping classes as well + * @type array + * @default [] + */ + "asDestroyStripes": [], + + /** + * If restoring a table - we should restore its width + * @type int + * @default 0 + */ + "sDestroyWidth": 0, + + /** + * Callback functions array for every time a row is inserted (i.e. on a draw). + * @type array + * @default [] + */ + "aoRowCallback": [], + + /** + * Callback functions for the header on each draw. + * @type array + * @default [] + */ + "aoHeaderCallback": [], + + /** + * Callback function for the footer on each draw. + * @type array + * @default [] + */ + "aoFooterCallback": [], + + /** + * Array of callback functions for draw callback functions + * @type array + * @default [] + */ + "aoDrawCallback": [], + + /** + * Array of callback functions for row created function + * @type array + * @default [] + */ + "aoRowCreatedCallback": [], + + /** + * Callback functions for just before the table is redrawn. A return of + * false will be used to cancel the draw. + * @type array + * @default [] + */ + "aoPreDrawCallback": [], + + /** + * Callback functions for when the table has been initialised. + * @type array + * @default [] + */ + "aoInitComplete": [], + + + /** + * Callbacks for modifying the settings to be stored for state saving, prior to + * saving state. + * @type array + * @default [] + */ + "aoStateSaveParams": [], + + /** + * Callbacks for modifying the settings that have been stored for state saving + * prior to using the stored values to restore the state. + * @type array + * @default [] + */ + "aoStateLoadParams": [], + + /** + * Callbacks for operating on the settings object once the saved state has been + * loaded + * @type array + * @default [] + */ + "aoStateLoaded": [], + + /** + * Cache the table ID for quick access + * @type string + * @default Empty string + */ + "sTableId": "", + + /** + * The TABLE node for the main table + * @type node + * @default null + */ + "nTable": null, + + /** + * Permanent ref to the thead element + * @type node + * @default null + */ + "nTHead": null, + + /** + * Permanent ref to the tfoot element - if it exists + * @type node + * @default null + */ + "nTFoot": null, + + /** + * Permanent ref to the tbody element + * @type node + * @default null + */ + "nTBody": null, + + /** + * Cache the wrapper node (contains all DataTables controlled elements) + * @type node + * @default null + */ + "nTableWrapper": null, + + /** + * Indicate if when using server-side processing the loading of data + * should be deferred until the second draw. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + * @default false + */ + "bDeferLoading": false, + + /** + * Indicate if all required information has been read in + * @type boolean + * @default false + */ + "bInitialised": false, + + /** + * Information about open rows. Each object in the array has the parameters + * 'nTr' and 'nParent' + * @type array + * @default [] + */ + "aoOpenRows": [], + + /** + * Dictate the positioning of DataTables' control elements - see + * {@link DataTable.model.oInit.sDom}. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default null + */ + "sDom": null, + + /** + * Which type of pagination should be used. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default two_button + */ + "sPaginationType": "two_button", + + /** + * The cookie duration (for bStateSave) in seconds. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type int + * @default 0 + */ + "iCookieDuration": 0, + + /** + * The cookie name prefix. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default Empty string + */ + "sCookiePrefix": "", + + /** + * Callback function for cookie creation. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + * @default null + */ + "fnCookieCallback": null, + + /** + * Array of callback functions for state saving. Each array element is an + * object with the following parameters: + *
      + *
    • function:fn - function to call. Takes two parameters, oSettings + * and the JSON string to save that has been thus far created. Returns + * a JSON string to be inserted into a json object + * (i.e. '"param": [ 0, 1, 2]')
    • + *
    • string:sName - name of callback
    • + *
    + * @type array + * @default [] + */ + "aoStateSave": [], + + /** + * Array of callback functions for state loading. Each array element is an + * object with the following parameters: + *
      + *
    • function:fn - function to call. Takes two parameters, oSettings + * and the object stored. May return false to cancel state loading
    • + *
    • string:sName - name of callback
    • + *
    + * @type array + * @default [] + */ + "aoStateLoad": [], + + /** + * State that was loaded from the cookie. Useful for back reference + * @type object + * @default null + */ + "oLoadedState": null, + + /** + * Source url for AJAX data for the table. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default null + */ + "sAjaxSource": null, + + /** + * Property from a given object from which to read the table data from. This + * can be an empty string (when not server-side processing), in which case + * it is assumed an an array is given directly. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sAjaxDataProp": null, + + /** + * Note if draw should be blocked while getting data + * @type boolean + * @default true + */ + "bAjaxDataGet": true, + + /** + * The last jQuery XHR object that was used for server-side data gathering. + * This can be used for working with the XHR information in one of the + * callbacks + * @type object + * @default null + */ + "jqXHR": null, + + /** + * Function to get the server-side data. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + */ + "fnServerData": null, + + /** + * Functions which are called prior to sending an Ajax request so extra + * parameters can easily be sent to the server + * @type array + * @default [] + */ + "aoServerParams": [], + + /** + * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if + * required). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sServerMethod": null, + + /** + * Format numbers for display. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + */ + "fnFormatNumber": null, + + /** + * List of options that can be used for the user selectable length menu. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @default [] + */ + "aLengthMenu": null, + + /** + * Counter for the draws that the table does. Also used as a tracker for + * server-side processing + * @type int + * @default 0 + */ + "iDraw": 0, + + /** + * Indicate if a redraw is being done - useful for Ajax + * @type boolean + * @default false + */ + "bDrawing": false, + + /** + * Draw index (iDraw) of the last error when parsing the returned data + * @type int + * @default -1 + */ + "iDrawError": -1, + + /** + * Paging display length + * @type int + * @default 10 + */ + "_iDisplayLength": 10, + + /** + * Paging start point - aiDisplay index + * @type int + * @default 0 + */ + "_iDisplayStart": 0, + + /** + * Paging end point - aiDisplay index. Use fnDisplayEnd rather than + * this property to get the end point + * @type int + * @default 10 + * @private + */ + "_iDisplayEnd": 10, + + /** + * Server-side processing - number of records in the result set + * (i.e. before filtering), Use fnRecordsTotal rather than + * this property to get the value of the number of records, regardless of + * the server-side processing setting. + * @type int + * @default 0 + * @private + */ + "_iRecordsTotal": 0, + + /** + * Server-side processing - number of records in the current display set + * (i.e. after filtering). Use fnRecordsDisplay rather than + * this property to get the value of the number of records, regardless of + * the server-side processing setting. + * @type boolean + * @default 0 + * @private + */ + "_iRecordsDisplay": 0, + + /** + * Flag to indicate if jQuery UI marking and classes should be used. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bJUI": null, + + /** + * The classes to use for the table + * @type object + * @default {} + */ + "oClasses": {}, + + /** + * Flag attached to the settings object so you can check in the draw + * callback if filtering has been done in the draw. Deprecated in favour of + * events. + * @type boolean + * @default false + * @deprecated + */ + "bFiltered": false, + + /** + * Flag attached to the settings object so you can check in the draw + * callback if sorting has been done in the draw. Deprecated in favour of + * events. + * @type boolean + * @default false + * @deprecated + */ + "bSorted": false, + + /** + * Indicate that if multiple rows are in the header and there is more than + * one unique cell per column, if the top one (true) or bottom one (false) + * should be used for sorting / title by DataTables. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSortCellsTop": null, + + /** + * Initialisation object that is used for the table + * @type object + * @default null + */ + "oInit": null, + + /** + * Destroy callback functions - for plug-ins to attach themselves to the + * destroy so they can clean up markup and events. + * @type array + * @default [] + */ + "aoDestroyCallback": [], + + + /** + * Get the number of records in the current record set, before filtering + * @type function + */ + "fnRecordsTotal": function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsTotal, 10); + } else { + return this.aiDisplayMaster.length; + } + }, + + /** + * Get the number of records in the current record set, after filtering + * @type function + */ + "fnRecordsDisplay": function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsDisplay, 10); + } else { + return this.aiDisplay.length; + } + }, + + /** + * Set the display end point - aiDisplay index + * @type function + * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here + */ + "fnDisplayEnd": function () + { + if ( this.oFeatures.bServerSide ) { + if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) { + return this._iDisplayStart+this.aiDisplay.length; + } else { + return Math.min( this._iDisplayStart+this._iDisplayLength, + this._iRecordsDisplay ); + } + } else { + return this._iDisplayEnd; + } + }, + + /** + * The DataTables object for this table + * @type object + * @default null + */ + "oInstance": null, + + /** + * Unique identifier for each instance of the DataTables object. If there + * is an ID on the table node, then it takes that value, otherwise an + * incrementing internal counter is used. + * @type string + * @default null + */ + "sInstance": null, + + /** + * tabindex attribute value that is added to DataTables control elements, allowing + * keyboard navigation of the table and its controls. + */ + "iTabIndex": 0, + + /** + * DIV container for the footer scrolling table if scrolling + */ + "nScrollHead": null, + + /** + * DIV container for the footer scrolling table if scrolling + */ + "nScrollFoot": null + }; + + /** + * Extension object for DataTables that is used to provide all extension options. + * + * Note that the DataTable.ext object is available through + * jQuery.fn.dataTable.ext where it may be accessed and manipulated. It is + * also aliased to jQuery.fn.dataTableExt for historic reasons. + * @namespace + * @extends DataTable.models.ext + */ + DataTable.ext = $.extend( true, {}, DataTable.models.ext ); + + $.extend( DataTable.ext.oStdClasses, { + "sTable": "dataTable", + + /* Two buttons buttons */ + "sPagePrevEnabled": "paginate_enabled_previous", + "sPagePrevDisabled": "paginate_disabled_previous", + "sPageNextEnabled": "paginate_enabled_next", + "sPageNextDisabled": "paginate_disabled_next", + "sPageJUINext": "", + "sPageJUIPrev": "", + + /* Full numbers paging buttons */ + "sPageButton": "paginate_button", + "sPageButtonActive": "paginate_active", + "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled", + "sPageFirst": "first", + "sPagePrevious": "previous", + "sPageNext": "next", + "sPageLast": "last", + + /* Striping classes */ + "sStripeOdd": "odd", + "sStripeEven": "even", + + /* Empty row */ + "sRowEmpty": "dataTables_empty", + + /* Features */ + "sWrapper": "dataTables_wrapper", + "sFilter": "dataTables_filter", + "sInfo": "dataTables_info", + "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ + "sLength": "dataTables_length", + "sProcessing": "dataTables_processing", + + /* Sorting */ + "sSortAsc": "sorting_asc", + "sSortDesc": "sorting_desc", + "sSortable": "sorting", /* Sortable in both directions */ + "sSortableAsc": "sorting_asc_disabled", + "sSortableDesc": "sorting_desc_disabled", + "sSortableNone": "sorting_disabled", + "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ + "sSortJUIAsc": "", + "sSortJUIDesc": "", + "sSortJUI": "", + "sSortJUIAscAllowed": "", + "sSortJUIDescAllowed": "", + "sSortJUIWrapper": "", + "sSortIcon": "", + + /* Scrolling */ + "sScrollWrapper": "dataTables_scroll", + "sScrollHead": "dataTables_scrollHead", + "sScrollHeadInner": "dataTables_scrollHeadInner", + "sScrollBody": "dataTables_scrollBody", + "sScrollFoot": "dataTables_scrollFoot", + "sScrollFootInner": "dataTables_scrollFootInner", + + /* Misc */ + "sFooterTH": "", + "sJUIHeader": "", + "sJUIFooter": "" + } ); + + + $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, { + /* Two buttons buttons */ + "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left", + "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled", + "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right", + "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled", + "sPageJUINext": "ui-icon ui-icon-circle-arrow-e", + "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w", + + /* Full numbers paging buttons */ + "sPageButton": "fg-button ui-button ui-state-default", + "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageFirst": "first ui-corner-tl ui-corner-bl", + "sPageLast": "last ui-corner-tr ui-corner-br", + + /* Features */ + "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ + "ui-buttonset-multi paging_", /* Note that the type is postfixed */ + + /* Sorting */ + "sSortAsc": "ui-state-default", + "sSortDesc": "ui-state-default", + "sSortable": "ui-state-default", + "sSortableAsc": "ui-state-default", + "sSortableDesc": "ui-state-default", + "sSortableNone": "ui-state-default", + "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n", + "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s", + "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s", + "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n", + "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s", + "sSortJUIWrapper": "DataTables_sort_wrapper", + "sSortIcon": "DataTables_sort_icon", + + /* Scrolling */ + "sScrollHead": "dataTables_scrollHead ui-state-default", + "sScrollFoot": "dataTables_scrollFoot ui-state-default", + + /* Misc */ + "sFooterTH": "ui-state-default", + "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix", + "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix" + } ); + + /* + * Variable: oPagination + * Purpose: + * Scope: jQuery.fn.dataTableExt + */ + $.extend( DataTable.ext.oPagination, { + /* + * Variable: two_button + * Purpose: Standard two button (forward/back) pagination + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "two_button": { + /* + * Function: oPagination.two_button.fnInit + * Purpose: Initialise dom elements required for pagination with forward/back buttons only + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) + { + var oLang = oSettings.oLanguage.oPaginate; + var oClasses = oSettings.oClasses; + var fnClickHandler = function ( e ) { + if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) + { + fnCallbackDraw( oSettings ); + } + }; + + var sAppend = (!oSettings.bJUI) ? + ''+oLang.sPrevious+''+ + ''+oLang.sNext+'' + : + ''+ + ''; + $(nPaging).append( sAppend ); + + var els = $('a', nPaging); + var nPrevious = els[0], + nNext = els[1]; + + oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); + + /* ID the first elements only */ + if ( !oSettings.aanFeatures.p ) + { + nPaging.id = oSettings.sTableId+'_paginate'; + nPrevious.id = oSettings.sTableId+'_previous'; + nNext.id = oSettings.sTableId+'_next'; + + nPrevious.setAttribute('aria-controls', oSettings.sTableId); + nNext.setAttribute('aria-controls', oSettings.sTableId); + } + }, + + /* + * Function: oPagination.two_button.fnUpdate + * Purpose: Update the two button pagination at the end of the draw + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + var oClasses = oSettings.oClasses; + var an = oSettings.aanFeatures.p; + var nNode; + + /* Loop over each instance of the pager */ + for ( var i=0, iLen=an.length ; i'+oLang.sFirst+''+ + ''+oLang.sPrevious+''+ + ''+ + ''+oLang.sNext+''+ + ''+oLang.sLast+'' + ); + var els = $('a', nPaging); + var nFirst = els[0], + nPrev = els[1], + nNext = els[2], + nLast = els[3]; + + oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler ); + + /* ID the first elements only */ + if ( !oSettings.aanFeatures.p ) + { + nPaging.id = oSettings.sTableId+'_paginate'; + nFirst.id =oSettings.sTableId+'_first'; + nPrev.id =oSettings.sTableId+'_previous'; + nNext.id =oSettings.sTableId+'_next'; + nLast.id =oSettings.sTableId+'_last'; + } + }, + + /* + * Function: oPagination.full_numbers.fnUpdate + * Purpose: Update the list of page buttons shows + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages; + var iPageCountHalf = Math.floor(iPageCount / 2); + var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength); + var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1; + var sList = ""; + var iStartButton, iEndButton, i, iLen; + var oClasses = oSettings.oClasses; + var anButtons, anStatic, nPaginateList, nNode; + var an = oSettings.aanFeatures.p; + var fnBind = function (j) { + oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) { + /* Use the information in the element to jump to the required page */ + oSettings.oApi._fnPageChange( oSettings, e.data.page ); + fnCallbackDraw( oSettings ); + e.preventDefault(); + } ); + }; + + /* Pages calculation */ + if ( oSettings._iDisplayLength === -1 ) + { + iStartButton = 1; + iEndButton = 1; + iCurrentPage = 1; + } + else if (iPages < iPageCount) + { + iStartButton = 1; + iEndButton = iPages; + } + else if (iCurrentPage <= iPageCountHalf) + { + iStartButton = 1; + iEndButton = iPageCount; + } + else if (iCurrentPage >= (iPages - iPageCountHalf)) + { + iStartButton = iPages - iPageCount + 1; + iEndButton = iPages; + } + else + { + iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1; + iEndButton = iStartButton + iPageCount - 1; + } + + + /* Build the dynamic list */ + for ( i=iStartButton ; i<=iEndButton ; i++ ) + { + sList += (iCurrentPage !== i) ? + ''+oSettings.fnFormatNumber(i)+'' : + ''+oSettings.fnFormatNumber(i)+''; + } + + /* Loop over each instance of the pager */ + for ( i=0, iLen=an.length ; i y) ? 1 : 0)); + }, + + "string-desc": function ( x, y ) + { + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * html sorting (ignore html tags) + */ + "html-pre": function ( a ) + { + return a.replace( /<.*?>/g, "" ).toLowerCase(); + }, + + "html-asc": function ( x, y ) + { + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + }, + + "html-desc": function ( x, y ) + { + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * date sorting + */ + "date-pre": function ( a ) + { + var x = Date.parse( a ); + + if ( isNaN(x) || x==="" ) + { + x = Date.parse( "01/01/1970 00:00:00" ); + } + return x; + }, + + "date-asc": function ( x, y ) + { + return x - y; + }, + + "date-desc": function ( x, y ) + { + return y - x; + }, + + + /* + * numerical sorting + */ + "numeric-pre": function ( a ) + { + return (a=="-" || a==="") ? 0 : a*1; + }, + + "numeric-asc": function ( x, y ) + { + return x - y; + }, + + "numeric-desc": function ( x, y ) + { + return y - x; + } + } ); + + + $.extend( DataTable.ext.aTypes, [ + /* + * Function: - + * Purpose: Check to see if a string is numeric + * Returns: string:'numeric' or null + * Inputs: mixed:sText - string to check + */ + function ( sData ) + { + /* Allow zero length strings as a number */ + if ( typeof sData === 'number' ) + { + return 'numeric'; + } + else if ( typeof sData !== 'string' ) + { + return null; + } + + var sValidFirstChars = "0123456789-"; + var sValidChars = "0123456789."; + var Char; + var bDecimal = false; + + /* Check for a valid first char (no period and allow negatives) */ + Char = sData.charAt(0); + if (sValidFirstChars.indexOf(Char) == -1) + { + return null; + } + + /* Check all the other characters are valid */ + for ( var i=1 ; i') != -1 ) + { + return 'html'; + } + return null; + } + ] ); + + + // jQuery aliases + $.fn.DataTable = DataTable; + $.fn.dataTable = DataTable; + $.fn.dataTableSettings = DataTable.settings; + $.fn.dataTableExt = DataTable.ext; + + + // Information about events fired by DataTables - for documentation. + /** + * Draw event, fired whenever the table is redrawn on the page, at the same point as + * fnDrawCallback. This may be useful for binding events or performing calculations when + * the table is altered at all. + * @name DataTable#draw + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Filter event, fired when the filtering applied to the table (using the build in global + * global filter, or column filters) is altered. + * @name DataTable#filter + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Page change event, fired when the paging of the table is altered. + * @name DataTable#page + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Sort event, fired when the sorting applied to the table is altered. + * @name DataTable#sort + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * DataTables initialisation complete event, fired when the table is fully drawn, + * including Ajax data loaded, if Ajax data is required. + * @name DataTable#init + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The JSON object request from the server - only + * present if client-side Ajax sourced data is used
  • + */ + + /** + * State save event, fired when the table has changed state a new state save is required. + * This method allows modification of the state saving object prior to actually doing the + * save, including addition or other state properties (for plug-ins) or modification + * of a DataTables core property. + * @name DataTable#stateSaveParams + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The state information to be saved + */ + + /** + * State load event, fired when the table is loading state from the stored data, but + * prior to the settings object being modified by the saved state - allowing modification + * of the saved state is required or loading of state for a plug-in. + * @name DataTable#stateLoadParams + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The saved state information + */ + + /** + * State loaded event, fired when state has been loaded from stored data and the settings + * object has been modified by the loaded data. + * @name DataTable#stateLoaded + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The saved state information + */ + + /** + * Processing event, fired when DataTables is doing some kind of processing (be it, + * sort, filter or anything else). Can be used to indicate to the end user that + * there is something happening, or that something has finished. + * @name DataTable#processing + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {boolean} bShow Flag for if DataTables is doing processing or not + */ + + /** + * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to + * made to the server for new data (note that this trigger is called in fnServerData, + * if you override fnServerData and which to use this event, you need to trigger it in + * you success function). + * @name DataTable#xhr + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + * @param {object} json JSON returned from the server + */ + + /** + * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing + * the bDestroy:true parameter in the initialisation object. This can be used to remove + * bound events, added DOM nodes, etc. + * @name DataTable#destroy + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ +})); + +}(window, document)); + diff --git a/plugins/web_gui/static/plugins/fancybox/blank.gif b/plugins/web_gui/static/plugins/fancybox/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..35d42e808f0a8017b8d52a06be2f8fec0b466a66 GIT binary patch literal 43 scmZ?wbhEHbWMp7uXkcLY|NlP&1B2pE7Dgb&paUX6G7L;iE{qJ;0LZEa`2YX_ literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/fancybox/fancybox_loading.gif b/plugins/web_gui/static/plugins/fancybox/fancybox_loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..a03a40c097ee728709f65d4ea7397903a389d484 GIT binary patch literal 6567 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 literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/fancybox/fancybox_loading@2x.gif b/plugins/web_gui/static/plugins/fancybox/fancybox_loading@2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..9205aeb09fffa6b571b4c6beee30b18400829c03 GIT binary patch literal 13984 zcmdtpX;f2(+Ar{(ot=4L0|COk2@%3*z%UvmBmq&;1`CRoVn8Z`pb=0JsqPHSQ$#>O zlpu(Ls8JA6P{W{NYc1kXYOM{3ii(OuTWdX>n;y^c^`4${?|t8U*In!0e1XN{3&Z}c z|NnWOELa%o9}vd{xWEAbfIvv4P>F@&!Tv!ui=7ak(7eBSVtj&O!iZcJ$@AuAre}7Z z=&Y=+yfJd)^~={(GPR_rBz#f$m9MV2ySk^Qq_(%U+gRDetcu|W@^i9tde8K}d;4zc z*;M_$`a5^;KzK-%rxJ&X2QLn?o!AL$6PjC^Cmu{N%o&l(BYD2O%*~mdU7huH^*3(a zc>T+3DxF$VRuaB6{L0lU?w;r>m0w%gd*#Kgw%=ks&6=k%WIeK+$C_{YoPuau=B zk)Mi!B_ZCPTr9@$b%);|5($_Gxc~7zfBcvLenz)X7Uph+@%iqcoEz9Md`R*#z-GR2 zt8dXVpW?ZVIZ+-Gx=Ycb(>>SzCy`;_Wwyar_cK7Wh&O zrlIseae92AkZ50;y?W<7KWti>V~)@`f6qLxhBEd3d4LHAEHdDkiYOs-Y)E{V> zW6~D2Vh>eoeqwMQvwM#Fl3qfgiFP)WjF1Bwg^0QQ6y5A-#_f4rQ>{ZN!bL)0FKcTj zmtREz>uarK!Iv6s=Pl9&3g{3SgfGt;U2si=UkR|9DQrcaG60u7isr@<0SI=eK&Fo^ zD5be?9#mQCKQjUyhnGl(MIkd-Q|7a?DLlO$K=fO7R5j{NxbUU>FJ2r>(*il^6xhiY z>VYN#BOC1&Nbi>(V6PW1W^Qu2@}*POh)!lqE&*prUJD90A6Ur~1Cn9C3_=KY-6?@2 z+kBkHC|pv+ec`({{OnGtI;_W%MbkT22*IID5#$9S zXvQ)C7@*nAY@T$WGDj4Gs1X2WF#xqhL=24KkO8B4T{q2%dO;l3^!ANQqQmk-HIRco zYYlba_0G!GuXnx?`&;QJn|JA-4k2QTD;$VyMqM~oZ3Y1Sv_
    bMxRL(pijsY@019xTxeF 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 literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/fancybox/fancybox_overlay.png b/plugins/web_gui/static/plugins/fancybox/fancybox_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..a4391396a9d6b6d7ff3b781f16904732fea40bdd GIT binary patch literal 1003 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 S1P^~LSQ@H2DwWEJcmD(3qHSjY literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/fancybox/helpers/fancybox_buttons.png b/plugins/web_gui/static/plugins/fancybox/helpers/fancybox_buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..07872072704114b91681e2e6f9697ce1521b64d2 GIT binary patch literal 1080 zcmeAS@N?(olHy`uVBq!ia0vp^Q6S903?%u>HW~n_y#YQUu0R?WSg~RSP%1Go5lD7* zbwQLpe*757ICA6&kW5WYZD?o!GK`Ilf#ib+545$lfs7|lo|Kf7golSGBqXd|yY}6? zcgK$(2by;H@Zldne!PGGe#3?hK*r6RH}~(~f9%+?@87@w1cMhZUi|v?>-O#24<9~! z_3G8{-@iY6_yAP-?b|mX`_G?0|Ns97D*W>0%coDDfKr0iiH$(}%u0g%f*BZ@S=qVy z1VzPVE?Tl=<;G1rjvPIE`Ra{3j~;*c^fm05 z&}0S%rZ1i@jv*CsZ>PnU&vFoGYh)GcNLbUk(XcbqE{E69EG*srz@Pu~uR3~FiyV{r zKBIe^jd`)*o5yoLKHYF_zn{1F51Du38}jGBJ=VP0ecMa>bF+9K`W*ijXIeka_uU8A z*POd= z37@}bnmsYU%ylPY9@}5u*!t|)yNM@Xh;kTr{CTM%UpgJrq;^z1sCv#Ff{JcXH0QycQ=j-SpqK)3sqC&x%d{>uv#p4L4W% zmLHbjTwSCP^ID(pX0NGG_)`a^m0!6nD|Dt#Dvad0vf#zR8xqRnG{y^pfbH6Kc3;s;HW4p`heoW(jKH<7AtsEly z$M&AE{dQl2(Z%x9#dt|gSIbWy<4Xjtobc#5EmRoE7k>Wa#EFw7ELWat{GexP^oT7` zWJjo_z_Z6E{wwPO!J9zw9U;?iErx;1Arv+D^&N20C4AEY>{Ek`B=i66zn9m4$^{AUqIL)kd`}_|Y zirXZ4+!kL{DD1t`cieXN&YnLTl;^yVdNTEd730M4<~70>Dwl5dOP&;N_1dH)?&X@x qGoDO6XT>`g#8(4K<@tG^_7CJ-u|B8Hp&OWk7(8A5T-G@yGywqna}dM; literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.css b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.css new file mode 100644 index 0000000..a26273a --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.css @@ -0,0 +1,97 @@ +#fancybox-buttons { + position: fixed; + left: 0; + width: 100%; + z-index: 8050; +} + +#fancybox-buttons.top { + top: 10px; +} + +#fancybox-buttons.bottom { + bottom: 10px; +} + +#fancybox-buttons ul { + display: block; + width: 166px; + height: 30px; + margin: 0 auto; + padding: 0; + list-style: none; + border: 1px solid #111; + border-radius: 3px; + -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); + -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); + box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); + background: rgb(50,50,50); + background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51))); + background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + background: linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 ); +} + +#fancybox-buttons ul li { + float: left; + margin: 0; + padding: 0; +} + +#fancybox-buttons a { + display: block; + width: 30px; + height: 30px; + text-indent: -9999px; + background-color: transparent; + background-image: url('fancybox_buttons.png'); + background-repeat: no-repeat; + outline: none; + opacity: 0.8; +} + +#fancybox-buttons a:hover { + opacity: 1; +} + +#fancybox-buttons a.btnPrev { + background-position: 5px 0; +} + +#fancybox-buttons a.btnNext { + background-position: -33px 0; + border-right: 1px solid #3e3e3e; +} + +#fancybox-buttons a.btnPlay { + background-position: 0 -30px; +} + +#fancybox-buttons a.btnPlayOn { + background-position: -30px -30px; +} + +#fancybox-buttons a.btnToggle { + background-position: 3px -60px; + border-left: 1px solid #111; + border-right: 1px solid #3e3e3e; + width: 35px +} + +#fancybox-buttons a.btnToggleOn { + background-position: -27px -60px; +} + +#fancybox-buttons a.btnClose { + border-left: 1px solid #111; + width: 35px; + background-position: -56px 0px; +} + +#fancybox-buttons a.btnDisabled { + opacity : 0.4; + cursor: default; +} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.js b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.js new file mode 100644 index 0000000..fd8b955 --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-buttons.js @@ -0,0 +1,122 @@ + /*! + * Buttons helper for fancyBox + * version: 1.0.5 (Mon, 15 Oct 2012) + * @requires fancyBox v2.0 or later + * + * Usage: + * $(".fancybox").fancybox({ + * helpers : { + * buttons: { + * position : 'top' + * } + * } + * }); + * + */ +(function ($) { + //Shortcut for fancyBox object + var F = $.fancybox; + + //Add helper object + F.helpers.buttons = { + defaults : { + skipSingle : false, // disables if gallery contains single image + position : 'top', // 'top' or 'bottom' + tpl : '

    ' + }, + + list : null, + buttons: null, + + beforeLoad: function (opts, obj) { + //Remove self if gallery do not have at least two items + + if (opts.skipSingle && obj.group.length < 2) { + obj.helpers.buttons = false; + obj.closeBtn = true; + + return; + } + + //Increase top margin to give space for buttons + obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30; + }, + + onPlayStart: function () { + if (this.buttons) { + this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn'); + } + }, + + onPlayEnd: function () { + if (this.buttons) { + this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn'); + } + }, + + afterShow: function (opts, obj) { + var buttons = this.buttons; + + if (!buttons) { + this.list = $(opts.tpl).addClass(opts.position).appendTo('body'); + + buttons = { + prev : this.list.find('.btnPrev').click( F.prev ), + next : this.list.find('.btnNext').click( F.next ), + play : this.list.find('.btnPlay').click( F.play ), + toggle : this.list.find('.btnToggle').click( F.toggle ), + close : this.list.find('.btnClose').click( F.close ) + } + } + + //Prev + if (obj.index > 0 || obj.loop) { + buttons.prev.removeClass('btnDisabled'); + } else { + buttons.prev.addClass('btnDisabled'); + } + + //Next / Play + if (obj.loop || obj.index < obj.group.length - 1) { + buttons.next.removeClass('btnDisabled'); + buttons.play.removeClass('btnDisabled'); + + } else { + buttons.next.addClass('btnDisabled'); + buttons.play.addClass('btnDisabled'); + } + + this.buttons = buttons; + + this.onUpdate(opts, obj); + }, + + onUpdate: function (opts, obj) { + var toggle; + + if (!this.buttons) { + return; + } + + toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn'); + + //Size toggle button + if (obj.canShrink) { + toggle.addClass('btnToggleOn'); + + } else if (!obj.canExpand) { + toggle.addClass('btnDisabled'); + } + }, + + beforeClose: function () { + if (this.list) { + this.list.remove(); + } + + this.list = null; + this.buttons = null; + } + }; + +}(jQuery)); diff --git a/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-media.js b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-media.js new file mode 100644 index 0000000..3584c8a --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-media.js @@ -0,0 +1,199 @@ +/*! + * Media helper for fancyBox + * version: 1.0.6 (Fri, 14 Jun 2013) + * @requires fancyBox v2.0 or later + * + * Usage: + * $(".fancybox").fancybox({ + * helpers : { + * media: true + * } + * }); + * + * Set custom URL parameters: + * $(".fancybox").fancybox({ + * helpers : { + * media: { + * youtube : { + * params : { + * autoplay : 0 + * } + * } + * } + * } + * }); + * + * Or: + * $(".fancybox").fancybox({, + * helpers : { + * media: true + * }, + * youtube : { + * autoplay: 0 + * } + * }); + * + * Supports: + * + * Youtube + * http://www.youtube.com/watch?v=opj24KnzrWo + * http://www.youtube.com/embed/opj24KnzrWo + * http://youtu.be/opj24KnzrWo + * http://www.youtube-nocookie.com/embed/opj24KnzrWo + * Vimeo + * http://vimeo.com/40648169 + * http://vimeo.com/channels/staffpicks/38843628 + * http://vimeo.com/groups/surrealism/videos/36516384 + * http://player.vimeo.com/video/45074303 + * Metacafe + * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/ + * http://www.metacafe.com/watch/7635964/ + * Dailymotion + * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people + * Twitvid + * http://twitvid.com/QY7MD + * Twitpic + * http://twitpic.com/7p93st + * Instagram + * http://instagr.am/p/IejkuUGxQn/ + * http://instagram.com/p/IejkuUGxQn/ + * Google maps + * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17 + * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16 + * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56 + */ +(function ($) { + "use strict"; + + //Shortcut for fancyBox object + var F = $.fancybox, + format = function( url, rez, params ) { + params = params || ''; + + if ( $.type( params ) === "object" ) { + params = $.param(params, true); + } + + $.each(rez, function(key, value) { + url = url.replace( '$' + key, value || '' ); + }); + + if (params.length) { + url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params; + } + + return url; + }; + + //Add helper object + F.helpers.media = { + defaults : { + youtube : { + matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i, + params : { + autoplay : 1, + autohide : 1, + fs : 1, + rel : 0, + hd : 1, + wmode : 'opaque', + enablejsapi : 1 + }, + type : 'iframe', + url : '//www.youtube.com/embed/$3' + }, + vimeo : { + matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/, + params : { + autoplay : 1, + hd : 1, + show_title : 1, + show_byline : 1, + show_portrait : 0, + fullscreen : 1 + }, + type : 'iframe', + url : '//player.vimeo.com/video/$1' + }, + metacafe : { + matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/, + params : { + autoPlay : 'yes' + }, + type : 'swf', + url : function( rez, params, obj ) { + obj.swf.flashVars = 'playerVars=' + $.param( params, true ); + + return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf'; + } + }, + dailymotion : { + matcher : /dailymotion.com\/video\/(.*)\/?(.*)/, + params : { + additionalInfos : 0, + autoStart : 1 + }, + type : 'swf', + url : '//www.dailymotion.com/swf/video/$1' + }, + twitvid : { + matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i, + params : { + autoplay : 0 + }, + type : 'iframe', + url : '//www.twitvid.com/embed.php?guid=$1' + }, + twitpic : { + matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i, + type : 'image', + url : '//twitpic.com/show/full/$1/' + }, + instagram : { + matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i, + type : 'image', + url : '//$1/p/$2/media/?size=l' + }, + google_maps : { + matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i, + type : 'iframe', + url : function( rez ) { + return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed'); + } + } + }, + + beforeLoad : function(opts, obj) { + var url = obj.href || '', + type = false, + what, + item, + rez, + params; + + for (what in opts) { + if (opts.hasOwnProperty(what)) { + item = opts[ what ]; + rez = url.match( item.matcher ); + + if (rez) { + type = item.type; + params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null)); + + url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params ); + + break; + } + } + } + + if (type) { + obj.href = url; + obj.type = type; + + obj.autoHeight = false; + } + } + }; + +}(jQuery)); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.css b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.css new file mode 100644 index 0000000..63d2943 --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.css @@ -0,0 +1,55 @@ +#fancybox-thumbs { + position: fixed; + left: 0; + width: 100%; + overflow: hidden; + z-index: 8050; +} + +#fancybox-thumbs.bottom { + bottom: 2px; +} + +#fancybox-thumbs.top { + top: 2px; +} + +#fancybox-thumbs ul { + position: relative; + list-style: none; + margin: 0; + padding: 0; +} + +#fancybox-thumbs ul li { + float: left; + padding: 1px; + opacity: 0.5; +} + +#fancybox-thumbs ul li.active { + opacity: 0.75; + padding: 0; + border: 1px solid #fff; +} + +#fancybox-thumbs ul li:hover { + opacity: 1; +} + +#fancybox-thumbs ul li a { + display: block; + position: relative; + overflow: hidden; + border: 1px solid #222; + background: #111; + outline: none; +} + +#fancybox-thumbs ul li img { + display: block; + position: relative; + border: 0; + padding: 0; + max-width: none; +} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.js b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.js new file mode 100644 index 0000000..5db3d4a --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/helpers/jquery.fancybox-thumbs.js @@ -0,0 +1,162 @@ + /*! + * Thumbnail helper for fancyBox + * version: 1.0.7 (Mon, 01 Oct 2012) + * @requires fancyBox v2.0 or later + * + * Usage: + * $(".fancybox").fancybox({ + * helpers : { + * thumbs: { + * width : 50, + * height : 50 + * } + * } + * }); + * + */ +(function ($) { + //Shortcut for fancyBox object + var F = $.fancybox; + + //Add helper object + F.helpers.thumbs = { + defaults : { + width : 50, // thumbnail width + height : 50, // thumbnail height + position : 'bottom', // 'top' or 'bottom' + source : function ( item ) { // function to obtain the URL of the thumbnail image + var href; + + if (item.element) { + href = $(item.element).find('img').attr('src'); + } + + if (!href && item.type === 'image' && item.href) { + href = item.href; + } + + return href; + } + }, + + wrap : null, + list : null, + width : 0, + + init: function (opts, obj) { + var that = this, + list, + thumbWidth = opts.width, + thumbHeight = opts.height, + thumbSource = opts.source; + + //Build list structure + list = ''; + + for (var n = 0; n < obj.group.length; n++) { + list += '
  • '; + } + + this.wrap = $('
    ').addClass(opts.position).appendTo('body'); + this.list = $('
      ' + list + '
    ').appendTo(this.wrap); + + //Load each thumbnail + $.each(obj.group, function (i) { + var href = thumbSource( obj.group[ i ] ); + + if (!href) { + return; + } + + $("").load(function () { + var width = this.width, + height = this.height, + widthRatio, heightRatio, parent; + + if (!that.list || !width || !height) { + return; + } + + //Calculate thumbnail width/height and center it + widthRatio = width / thumbWidth; + heightRatio = height / thumbHeight; + + parent = that.list.children().eq(i).find('a'); + + if (widthRatio >= 1 && heightRatio >= 1) { + if (widthRatio > heightRatio) { + width = Math.floor(width / heightRatio); + height = thumbHeight; + + } else { + width = thumbWidth; + height = Math.floor(height / widthRatio); + } + } + + $(this).css({ + width : width, + height : height, + top : Math.floor(thumbHeight / 2 - height / 2), + left : Math.floor(thumbWidth / 2 - width / 2) + }); + + parent.width(thumbWidth).height(thumbHeight); + + $(this).hide().appendTo(parent).fadeIn(300); + + }).attr('src', href); + }); + + //Set initial width + this.width = this.list.children().eq(0).outerWidth(true); + + this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))); + }, + + beforeLoad: function (opts, obj) { + //Remove self if gallery do not have at least two items + if (obj.group.length < 2) { + obj.helpers.thumbs = false; + + return; + } + + //Increase bottom margin to give space for thumbs + obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15); + }, + + afterShow: function (opts, obj) { + //Check if exists and create or update list + if (this.list) { + this.onUpdate(opts, obj); + + } else { + this.init(opts, obj); + } + + //Set active element + this.list.children().removeClass('active').eq(obj.index).addClass('active'); + }, + + //Center list + onUpdate: function (opts, obj) { + if (this.list) { + this.list.stop(true).animate({ + 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)) + }, 150); + } + }, + + beforeClose: function () { + if (this.wrap) { + this.wrap.remove(); + } + + this.wrap = null; + this.list = null; + this.width = 0; + } + } + +}(jQuery)); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.css b/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.css new file mode 100644 index 0000000..367890a --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.css @@ -0,0 +1,274 @@ +/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ +.fancybox-wrap, +.fancybox-skin, +.fancybox-outer, +.fancybox-inner, +.fancybox-image, +.fancybox-wrap iframe, +.fancybox-wrap object, +.fancybox-nav, +.fancybox-nav span, +.fancybox-tmp +{ + padding: 0; + margin: 0; + border: 0; + outline: none; + vertical-align: top; +} + +.fancybox-wrap { + position: absolute; + top: 0; + left: 0; + z-index: 8020; +} + +.fancybox-skin { + position: relative; + background: #f9f9f9; + color: #444; + text-shadow: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.fancybox-opened { + z-index: 8030; +} + +.fancybox-opened .fancybox-skin { + -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); +} + +.fancybox-outer, .fancybox-inner { + position: relative; +} + +.fancybox-inner { + overflow: hidden; +} + +.fancybox-type-iframe .fancybox-inner { + -webkit-overflow-scrolling: touch; +} + +.fancybox-error { + color: #444; + font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; + margin: 0; + padding: 15px; + white-space: nowrap; +} + +.fancybox-image, .fancybox-iframe { + display: block; + width: 100%; + height: 100%; +} + +.fancybox-image { + max-width: 100%; + max-height: 100%; +} + +#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { + background-image: url('fancybox_sprite.png'); +} + +#fancybox-loading { + position: fixed; + top: 50%; + left: 50%; + margin-top: -22px; + margin-left: -22px; + background-position: 0 -108px; + opacity: 0.8; + cursor: pointer; + z-index: 8060; +} + +#fancybox-loading div { + width: 44px; + height: 44px; + background: url('fancybox_loading.gif') center center no-repeat; +} + +.fancybox-close { + position: absolute; + top: -18px; + right: -18px; + width: 36px; + height: 36px; + cursor: pointer; + z-index: 8040; +} + +.fancybox-nav { + position: absolute; + top: 0; + width: 40%; + height: 100%; + cursor: pointer; + text-decoration: none; + background: transparent url('blank.gif'); /* helps IE */ + -webkit-tap-highlight-color: rgba(0,0,0,0); + z-index: 8040; +} + +.fancybox-prev { + left: 0; +} + +.fancybox-next { + right: 0; +} + +.fancybox-nav span { + position: absolute; + top: 50%; + width: 36px; + height: 34px; + margin-top: -18px; + cursor: pointer; + z-index: 8040; + visibility: hidden; +} + +.fancybox-prev span { + left: 10px; + background-position: 0 -36px; +} + +.fancybox-next span { + right: 10px; + background-position: 0 -72px; +} + +.fancybox-nav:hover span { + visibility: visible; +} + +.fancybox-tmp { + position: absolute; + top: -99999px; + left: -99999px; + visibility: hidden; + max-width: 99999px; + max-height: 99999px; + overflow: visible !important; +} + +/* Overlay helper */ + +.fancybox-lock { + overflow: hidden !important; + width: auto; +} + +.fancybox-lock body { + overflow: hidden !important; +} + +.fancybox-lock-test { + overflow-y: hidden !important; +} + +.fancybox-overlay { + position: absolute; + top: 0; + left: 0; + overflow: hidden; + display: none; + z-index: 8010; + background: url('fancybox_overlay.png'); +} + +.fancybox-overlay-fixed { + position: fixed; + bottom: 0; + right: 0; +} + +.fancybox-lock .fancybox-overlay { + overflow: auto; + overflow-y: scroll; +} + +/* Title helper */ + +.fancybox-title { + visibility: hidden; + font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; + position: relative; + text-shadow: none; + z-index: 8050; +} + +.fancybox-opened .fancybox-title { + visibility: visible; +} + +.fancybox-title-float-wrap { + position: absolute; + bottom: 0; + right: 50%; + margin-bottom: -35px; + z-index: 8050; + text-align: center; +} + +.fancybox-title-float-wrap .child { + display: inline-block; + margin-right: -100%; + padding: 2px 20px; + background: transparent; /* Fallback for web browsers that doesn't support RGBa */ + background: rgba(0, 0, 0, 0.8); + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; + text-shadow: 0 1px 2px #222; + color: #FFF; + font-weight: bold; + line-height: 24px; + white-space: nowrap; +} + +.fancybox-title-outside-wrap { + position: relative; + margin-top: 10px; + color: #fff; +} + +.fancybox-title-inside-wrap { + padding-top: 10px; +} + +.fancybox-title-over-wrap { + position: absolute; + bottom: 0; + left: 0; + color: #fff; + padding: 10px; + background: #000; + background: rgba(0, 0, 0, .8); +} + +/*Retina graphics!*/ +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), + only screen and (min--moz-device-pixel-ratio: 1.5), + only screen and (min-device-pixel-ratio: 1.5){ + + #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { + background-image: url('fancybox_sprite@2x.png'); + background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/ + } + + #fancybox-loading div { + background-image: url('fancybox_loading@2x.gif'); + background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/ + } +} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.js b/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.js new file mode 100644 index 0000000..e8e1987 --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.js @@ -0,0 +1,2020 @@ +/*! + * fancyBox - jQuery Plugin + * version: 2.1.5 (Fri, 14 Jun 2013) + * @requires jQuery v1.6 or later + * + * Examples at http://fancyapps.com/fancybox/ + * License: www.fancyapps.com/fancybox/#license + * + * Copyright 2012 Janis Skarnelis - janis@fancyapps.com + * + */ + +(function (window, document, $, undefined) { + "use strict"; + + var H = $("html"), + W = $(window), + D = $(document), + F = $.fancybox = function () { + F.open.apply( this, arguments ); + }, + IE = navigator.userAgent.match(/msie/i), + didUpdate = null, + isTouch = document.createTouch !== undefined, + + isQuery = function(obj) { + return obj && obj.hasOwnProperty && obj instanceof $; + }, + isString = function(str) { + return str && $.type(str) === "string"; + }, + isPercentage = function(str) { + return isString(str) && str.indexOf('%') > 0; + }, + isScrollable = function(el) { + return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); + }, + getScalar = function(orig, dim) { + var value = parseInt(orig, 10) || 0; + + if (dim && isPercentage(orig)) { + value = F.getViewport()[ dim ] / 100 * value; + } + + return Math.ceil(value); + }, + getValue = function(value, dim) { + return getScalar(value, dim) + 'px'; + }; + + $.extend(F, { + // The current version of fancyBox + version: '2.1.5', + + defaults: { + padding : 15, + margin : 20, + + width : 800, + height : 600, + minWidth : 100, + minHeight : 100, + maxWidth : 9999, + maxHeight : 9999, + pixelRatio: 1, // Set to 2 for retina display support + + autoSize : true, + autoHeight : false, + autoWidth : false, + + autoResize : true, + autoCenter : !isTouch, + fitToView : true, + aspectRatio : false, + topRatio : 0.5, + leftRatio : 0.5, + + scrolling : 'auto', // 'auto', 'yes' or 'no' + wrapCSS : '', + + arrows : true, + closeBtn : true, + closeClick : false, + nextClick : false, + mouseWheel : true, + autoPlay : false, + playSpeed : 3000, + preload : 3, + modal : false, + loop : true, + + ajax : { + dataType : 'html', + headers : { 'X-fancyBox': true } + }, + iframe : { + scrolling : 'auto', + preload : true + }, + swf : { + wmode: 'transparent', + allowfullscreen : 'true', + allowscriptaccess : 'always' + }, + + keys : { + next : { + 13 : 'left', // enter + 34 : 'up', // page down + 39 : 'left', // right arrow + 40 : 'up' // down arrow + }, + prev : { + 8 : 'right', // backspace + 33 : 'down', // page up + 37 : 'right', // left arrow + 38 : 'down' // up arrow + }, + close : [27], // escape key + play : [32], // space - start/stop slideshow + toggle : [70] // letter "f" - toggle fullscreen + }, + + direction : { + next : 'left', + prev : 'right' + }, + + scrollOutside : true, + + // Override some properties + index : 0, + type : null, + href : null, + content : null, + title : null, + + // HTML templates + tpl: { + wrap : '
    ', + image : '', + iframe : '', + error : '

    The requested content cannot be loaded.
    Please try again later.

    ', + closeBtn : '', + next : '', + prev : '' + }, + + // Properties for each animation type + // Opening fancyBox + openEffect : 'fade', // 'elastic', 'fade' or 'none' + openSpeed : 250, + openEasing : 'swing', + openOpacity : true, + openMethod : 'zoomIn', + + // Closing fancyBox + closeEffect : 'fade', // 'elastic', 'fade' or 'none' + closeSpeed : 250, + closeEasing : 'swing', + closeOpacity : true, + closeMethod : 'zoomOut', + + // Changing next gallery item + nextEffect : 'elastic', // 'elastic', 'fade' or 'none' + nextSpeed : 250, + nextEasing : 'swing', + nextMethod : 'changeIn', + + // Changing previous gallery item + prevEffect : 'elastic', // 'elastic', 'fade' or 'none' + prevSpeed : 250, + prevEasing : 'swing', + prevMethod : 'changeOut', + + // Enable default helpers + helpers : { + overlay : true, + title : true + }, + + // Callbacks + onCancel : $.noop, // If canceling + beforeLoad : $.noop, // Before loading + afterLoad : $.noop, // After loading + beforeShow : $.noop, // Before changing in current item + afterShow : $.noop, // After opening + beforeChange : $.noop, // Before changing gallery item + beforeClose : $.noop, // Before closing + afterClose : $.noop // After closing + }, + + //Current state + group : {}, // Selected group + opts : {}, // Group options + previous : null, // Previous element + coming : null, // Element being loaded + current : null, // Currently loaded element + isActive : false, // Is activated + isOpen : false, // Is currently open + isOpened : false, // Have been fully opened at least once + + wrap : null, + skin : null, + outer : null, + inner : null, + + player : { + timer : null, + isActive : false + }, + + // Loaders + ajaxLoad : null, + imgPreload : null, + + // Some collections + transitions : {}, + helpers : {}, + + /* + * Static methods + */ + + open: function (group, opts) { + if (!group) { + return; + } + + if (!$.isPlainObject(opts)) { + opts = {}; + } + + // Close if already active + if (false === F.close(true)) { + return; + } + + // Normalize group + if (!$.isArray(group)) { + group = isQuery(group) ? $(group).get() : [group]; + } + + // Recheck if the type of each element is `object` and set content type (image, ajax, etc) + $.each(group, function(i, element) { + var obj = {}, + href, + title, + content, + type, + rez, + hrefParts, + selector; + + if ($.type(element) === "object") { + // Check if is DOM element + if (element.nodeType) { + element = $(element); + } + + if (isQuery(element)) { + obj = { + href : element.data('fancybox-href') || element.attr('href'), + title : element.data('fancybox-title') || element.attr('title'), + isDom : true, + element : element + }; + + if ($.metadata) { + $.extend(true, obj, element.metadata()); + } + + } else { + obj = element; + } + } + + href = opts.href || obj.href || (isString(element) ? element : null); + title = opts.title !== undefined ? opts.title : obj.title || ''; + + content = opts.content || obj.content; + type = content ? 'html' : (opts.type || obj.type); + + if (!type && obj.isDom) { + type = element.data('fancybox-type'); + + if (!type) { + rez = element.prop('class').match(/fancybox\.(\w+)/); + type = rez ? rez[1] : null; + } + } + + if (isString(href)) { + // Try to guess the content type + if (!type) { + if (F.isImage(href)) { + type = 'image'; + + } else if (F.isSWF(href)) { + type = 'swf'; + + } else if (href.charAt(0) === '#') { + type = 'inline'; + + } else if (isString(element)) { + type = 'html'; + content = element; + } + } + + // Split url into two pieces with source url and content selector, e.g, + // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" + if (type === 'ajax') { + hrefParts = href.split(/\s+/, 2); + href = hrefParts.shift(); + selector = hrefParts.shift(); + } + } + + if (!content) { + if (type === 'inline') { + if (href) { + content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 + + } else if (obj.isDom) { + content = element; + } + + } else if (type === 'html') { + content = href; + + } else if (!type && !href && obj.isDom) { + type = 'inline'; + content = element; + } + } + + $.extend(obj, { + href : href, + type : type, + content : content, + title : title, + selector : selector + }); + + group[ i ] = obj; + }); + + // Extend the defaults + F.opts = $.extend(true, {}, F.defaults, opts); + + // All options are merged recursive except keys + if (opts.keys !== undefined) { + F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; + } + + F.group = group; + + return F._start(F.opts.index); + }, + + // Cancel image loading or abort ajax request + cancel: function () { + var coming = F.coming; + + if (!coming || false === F.trigger('onCancel')) { + return; + } + + F.hideLoading(); + + if (F.ajaxLoad) { + F.ajaxLoad.abort(); + } + + F.ajaxLoad = null; + + if (F.imgPreload) { + F.imgPreload.onload = F.imgPreload.onerror = null; + } + + if (coming.wrap) { + coming.wrap.stop(true, true).trigger('onReset').remove(); + } + + F.coming = null; + + // If the first item has been canceled, then clear everything + if (!F.current) { + F._afterZoomOut( coming ); + } + }, + + // Start closing animation if is open; remove immediately if opening/closing + close: function (event) { + F.cancel(); + + if (false === F.trigger('beforeClose')) { + return; + } + + F.unbindEvents(); + + if (!F.isActive) { + return; + } + + if (!F.isOpen || event === true) { + $('.fancybox-wrap').stop(true).trigger('onReset').remove(); + + F._afterZoomOut(); + + } else { + F.isOpen = F.isOpened = false; + F.isClosing = true; + + $('.fancybox-item, .fancybox-nav').remove(); + + F.wrap.stop(true, true).removeClass('fancybox-opened'); + + F.transitions[ F.current.closeMethod ](); + } + }, + + // Manage slideshow: + // $.fancybox.play(); - toggle slideshow + // $.fancybox.play( true ); - start + // $.fancybox.play( false ); - stop + play: function ( action ) { + var clear = function () { + clearTimeout(F.player.timer); + }, + set = function () { + clear(); + + if (F.current && F.player.isActive) { + F.player.timer = setTimeout(F.next, F.current.playSpeed); + } + }, + stop = function () { + clear(); + + D.unbind('.player'); + + F.player.isActive = false; + + F.trigger('onPlayEnd'); + }, + start = function () { + if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { + F.player.isActive = true; + + D.bind({ + 'onCancel.player beforeClose.player' : stop, + 'onUpdate.player' : set, + 'beforeLoad.player' : clear + }); + + set(); + + F.trigger('onPlayStart'); + } + }; + + if (action === true || (!F.player.isActive && action !== false)) { + start(); + } else { + stop(); + } + }, + + // Navigate to next gallery item + next: function ( direction ) { + var current = F.current; + + if (current) { + if (!isString(direction)) { + direction = current.direction.next; + } + + F.jumpto(current.index + 1, direction, 'next'); + } + }, + + // Navigate to previous gallery item + prev: function ( direction ) { + var current = F.current; + + if (current) { + if (!isString(direction)) { + direction = current.direction.prev; + } + + F.jumpto(current.index - 1, direction, 'prev'); + } + }, + + // Navigate to gallery item by index + jumpto: function ( index, direction, router ) { + var current = F.current; + + if (!current) { + return; + } + + index = getScalar(index); + + F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; + F.router = router || 'jumpto'; + + if (current.loop) { + if (index < 0) { + index = current.group.length + (index % current.group.length); + } + + index = index % current.group.length; + } + + if (current.group[ index ] !== undefined) { + F.cancel(); + + F._start(index); + } + }, + + // Center inside viewport and toggle position type to fixed or absolute if needed + reposition: function (e, onlyAbsolute) { + var current = F.current, + wrap = current ? current.wrap : null, + pos; + + if (wrap) { + pos = F._getPosition(onlyAbsolute); + + if (e && e.type === 'scroll') { + delete pos.position; + + wrap.stop(true, true).animate(pos, 200); + + } else { + wrap.css(pos); + + current.pos = $.extend({}, current.dim, pos); + } + } + }, + + update: function (e) { + var type = (e && e.type), + anyway = !type || type === 'orientationchange'; + + if (anyway) { + clearTimeout(didUpdate); + + didUpdate = null; + } + + if (!F.isOpen || didUpdate) { + return; + } + + didUpdate = setTimeout(function() { + var current = F.current; + + if (!current || F.isClosing) { + return; + } + + F.wrap.removeClass('fancybox-tmp'); + + if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { + F._setDimension(); + } + + if (!(type === 'scroll' && current.canShrink)) { + F.reposition(e); + } + + F.trigger('onUpdate'); + + didUpdate = null; + + }, (anyway && !isTouch ? 0 : 300)); + }, + + // Shrink content to fit inside viewport or restore if resized + toggle: function ( action ) { + if (F.isOpen) { + F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; + + // Help browser to restore document dimensions + if (isTouch) { + F.wrap.removeAttr('style').addClass('fancybox-tmp'); + + F.trigger('onUpdate'); + } + + F.update(); + } + }, + + hideLoading: function () { + D.unbind('.loading'); + + $('#fancybox-loading').remove(); + }, + + showLoading: function () { + var el, viewport; + + F.hideLoading(); + + el = $('
    ').click(F.cancel).appendTo('body'); + + // If user will press the escape-button, the request will be canceled + D.bind('keydown.loading', function(e) { + if ((e.which || e.keyCode) === 27) { + e.preventDefault(); + + F.cancel(); + } + }); + + if (!F.defaults.fixed) { + viewport = F.getViewport(); + + el.css({ + position : 'absolute', + top : (viewport.h * 0.5) + viewport.y, + left : (viewport.w * 0.5) + viewport.x + }); + } + }, + + getViewport: function () { + var locked = (F.current && F.current.locked) || false, + rez = { + x: W.scrollLeft(), + y: W.scrollTop() + }; + + if (locked) { + rez.w = locked[0].clientWidth; + rez.h = locked[0].clientHeight; + + } else { + // See http://bugs.jquery.com/ticket/6724 + rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); + rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); + } + + return rez; + }, + + // Unbind the keyboard / clicking actions + unbindEvents: function () { + if (F.wrap && isQuery(F.wrap)) { + F.wrap.unbind('.fb'); + } + + D.unbind('.fb'); + W.unbind('.fb'); + }, + + bindEvents: function () { + var current = F.current, + keys; + + if (!current) { + return; + } + + // Changing document height on iOS devices triggers a 'resize' event, + // that can change document height... repeating infinitely + W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); + + keys = current.keys; + + if (keys) { + D.bind('keydown.fb', function (e) { + var code = e.which || e.keyCode, + target = e.target || e.srcElement; + + // Skip esc key if loading, because showLoading will cancel preloading + if (code === 27 && F.coming) { + return false; + } + + // Ignore key combinations and key events within form elements + if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { + $.each(keys, function(i, val) { + if (current.group.length > 1 && val[ code ] !== undefined) { + F[ i ]( val[ code ] ); + + e.preventDefault(); + return false; + } + + if ($.inArray(code, val) > -1) { + F[ i ] (); + + e.preventDefault(); + return false; + } + }); + } + }); + } + + if ($.fn.mousewheel && current.mouseWheel) { + F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { + var target = e.target || null, + parent = $(target), + canScroll = false; + + while (parent.length) { + if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { + break; + } + + canScroll = isScrollable( parent[0] ); + parent = $(parent).parent(); + } + + if (delta !== 0 && !canScroll) { + if (F.group.length > 1 && !current.canShrink) { + if (deltaY > 0 || deltaX > 0) { + F.prev( deltaY > 0 ? 'down' : 'left' ); + + } else if (deltaY < 0 || deltaX < 0) { + F.next( deltaY < 0 ? 'up' : 'right' ); + } + + e.preventDefault(); + } + } + }); + } + }, + + trigger: function (event, o) { + var ret, obj = o || F.coming || F.current; + + if (!obj) { + return; + } + + if ($.isFunction( obj[event] )) { + ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); + } + + if (ret === false) { + return false; + } + + if (obj.helpers) { + $.each(obj.helpers, function (helper, opts) { + if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { + F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj); + } + }); + } + + D.trigger(event); + }, + + isImage: function (str) { + return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); + }, + + isSWF: function (str) { + return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); + }, + + _start: function (index) { + var coming = {}, + obj, + href, + type, + margin, + padding; + + index = getScalar( index ); + obj = F.group[ index ] || null; + + if (!obj) { + return false; + } + + coming = $.extend(true, {}, F.opts, obj); + + // Convert margin and padding properties to array - top, right, bottom, left + margin = coming.margin; + padding = coming.padding; + + if ($.type(margin) === 'number') { + coming.margin = [margin, margin, margin, margin]; + } + + if ($.type(padding) === 'number') { + coming.padding = [padding, padding, padding, padding]; + } + + // 'modal' propery is just a shortcut + if (coming.modal) { + $.extend(true, coming, { + closeBtn : false, + closeClick : false, + nextClick : false, + arrows : false, + mouseWheel : false, + keys : null, + helpers: { + overlay : { + closeClick : false + } + } + }); + } + + // 'autoSize' property is a shortcut, too + if (coming.autoSize) { + coming.autoWidth = coming.autoHeight = true; + } + + if (coming.width === 'auto') { + coming.autoWidth = true; + } + + if (coming.height === 'auto') { + coming.autoHeight = true; + } + + /* + * Add reference to the group, so it`s possible to access from callbacks, example: + * afterLoad : function() { + * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); + * } + */ + + coming.group = F.group; + coming.index = index; + + // Give a chance for callback or helpers to update coming item (type, title, etc) + F.coming = coming; + + if (false === F.trigger('beforeLoad')) { + F.coming = null; + + return; + } + + type = coming.type; + href = coming.href; + + if (!type) { + F.coming = null; + + //If we can not determine content type then drop silently or display next/prev item if looping through gallery + if (F.current && F.router && F.router !== 'jumpto') { + F.current.index = index; + + return F[ F.router ]( F.direction ); + } + + return false; + } + + F.isActive = true; + + if (type === 'image' || type === 'swf') { + coming.autoHeight = coming.autoWidth = false; + coming.scrolling = 'visible'; + } + + if (type === 'image') { + coming.aspectRatio = true; + } + + if (type === 'iframe' && isTouch) { + coming.scrolling = 'scroll'; + } + + // Build the neccessary markup + coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); + + $.extend(coming, { + skin : $('.fancybox-skin', coming.wrap), + outer : $('.fancybox-outer', coming.wrap), + inner : $('.fancybox-inner', coming.wrap) + }); + + $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { + coming.skin.css('padding' + v, getValue(coming.padding[ i ])); + }); + + F.trigger('onReady'); + + // Check before try to load; 'inline' and 'html' types need content, others - href + if (type === 'inline' || type === 'html') { + if (!coming.content || !coming.content.length) { + return F._error( 'content' ); + } + + } else if (!href) { + return F._error( 'href' ); + } + + if (type === 'image') { + F._loadImage(); + + } else if (type === 'ajax') { + F._loadAjax(); + + } else if (type === 'iframe') { + F._loadIframe(); + + } else { + F._afterLoad(); + } + }, + + _error: function ( type ) { + $.extend(F.coming, { + type : 'html', + autoWidth : true, + autoHeight : true, + minWidth : 0, + minHeight : 0, + scrolling : 'no', + hasError : type, + content : F.coming.tpl.error + }); + + F._afterLoad(); + }, + + _loadImage: function () { + // Reset preload image so it is later possible to check "complete" property + var img = F.imgPreload = new Image(); + + img.onload = function () { + this.onload = this.onerror = null; + + F.coming.width = this.width / F.opts.pixelRatio; + F.coming.height = this.height / F.opts.pixelRatio; + + F._afterLoad(); + }; + + img.onerror = function () { + this.onload = this.onerror = null; + + F._error( 'image' ); + }; + + img.src = F.coming.href; + + if (img.complete !== true) { + F.showLoading(); + } + }, + + _loadAjax: function () { + var coming = F.coming; + + F.showLoading(); + + F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { + url: coming.href, + error: function (jqXHR, textStatus) { + if (F.coming && textStatus !== 'abort') { + F._error( 'ajax', jqXHR ); + + } else { + F.hideLoading(); + } + }, + success: function (data, textStatus) { + if (textStatus === 'success') { + coming.content = data; + + F._afterLoad(); + } + } + })); + }, + + _loadIframe: function() { + var coming = F.coming, + iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) + .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) + .attr('src', coming.href); + + // This helps IE + $(coming.wrap).bind('onReset', function () { + try { + $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); + } catch (e) {} + }); + + if (coming.iframe.preload) { + F.showLoading(); + + iframe.one('load', function() { + $(this).data('ready', 1); + + // iOS will lose scrolling if we resize + if (!isTouch) { + $(this).bind('load.fb', F.update); + } + + // Without this trick: + // - iframe won't scroll on iOS devices + // - IE7 sometimes displays empty iframe + $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); + + F._afterLoad(); + }); + } + + coming.content = iframe.appendTo( coming.inner ); + + if (!coming.iframe.preload) { + F._afterLoad(); + } + }, + + _preloadImages: function() { + var group = F.group, + current = F.current, + len = group.length, + cnt = current.preload ? Math.min(current.preload, len - 1) : 0, + item, + i; + + for (i = 1; i <= cnt; i += 1) { + item = group[ (current.index + i ) % len ]; + + if (item.type === 'image' && item.href) { + new Image().src = item.href; + } + } + }, + + _afterLoad: function () { + var coming = F.coming, + previous = F.current, + placeholder = 'fancybox-placeholder', + current, + content, + type, + scrolling, + href, + embed; + + F.hideLoading(); + + if (!coming || F.isActive === false) { + return; + } + + if (false === F.trigger('afterLoad', coming, previous)) { + coming.wrap.stop(true).trigger('onReset').remove(); + + F.coming = null; + + return; + } + + if (previous) { + F.trigger('beforeChange', previous); + + previous.wrap.stop(true).removeClass('fancybox-opened') + .find('.fancybox-item, .fancybox-nav') + .remove(); + } + + F.unbindEvents(); + + current = coming; + content = coming.content; + type = coming.type; + scrolling = coming.scrolling; + + $.extend(F, { + wrap : current.wrap, + skin : current.skin, + outer : current.outer, + inner : current.inner, + current : current, + previous : previous + }); + + href = current.href; + + switch (type) { + case 'inline': + case 'ajax': + case 'html': + if (current.selector) { + content = $('
    ').html(content).find(current.selector); + + } else if (isQuery(content)) { + if (!content.data(placeholder)) { + content.data(placeholder, $('
    ').insertAfter( content ).hide() ); + } + + content = content.show().detach(); + + current.wrap.bind('onReset', function () { + if ($(this).find(content).length) { + content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); + } + }); + } + break; + + case 'image': + content = current.tpl.image.replace('{href}', href); + break; + + case 'swf': + content = ''; + embed = ''; + + $.each(current.swf, function(name, val) { + content += ''; + embed += ' ' + name + '="' + val + '"'; + }); + + content += ''; + break; + } + + if (!(isQuery(content) && content.parent().is(current.inner))) { + current.inner.append( content ); + } + + // Give a chance for helpers or callbacks to update elements + F.trigger('beforeShow'); + + // Set scrolling before calculating dimensions + current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); + + // Set initial dimensions and start position + F._setDimension(); + + F.reposition(); + + F.isOpen = false; + F.coming = null; + + F.bindEvents(); + + if (!F.isOpened) { + $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); + + } else if (previous.prevMethod) { + F.transitions[ previous.prevMethod ](); + } + + F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); + + F._preloadImages(); + }, + + _setDimension: function () { + var viewport = F.getViewport(), + steps = 0, + canShrink = false, + canExpand = false, + wrap = F.wrap, + skin = F.skin, + inner = F.inner, + current = F.current, + width = current.width, + height = current.height, + minWidth = current.minWidth, + minHeight = current.minHeight, + maxWidth = current.maxWidth, + maxHeight = current.maxHeight, + scrolling = current.scrolling, + scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, + margin = current.margin, + wMargin = getScalar(margin[1] + margin[3]), + hMargin = getScalar(margin[0] + margin[2]), + wPadding, + hPadding, + wSpace, + hSpace, + origWidth, + origHeight, + origMaxWidth, + origMaxHeight, + ratio, + width_, + height_, + maxWidth_, + maxHeight_, + iframe, + body; + + // Reset dimensions so we could re-check actual size + wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); + + wPadding = getScalar(skin.outerWidth(true) - skin.width()); + hPadding = getScalar(skin.outerHeight(true) - skin.height()); + + // Any space between content and viewport (margin, padding, border, title) + wSpace = wMargin + wPadding; + hSpace = hMargin + hPadding; + + origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; + origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; + + if (current.type === 'iframe') { + iframe = current.content; + + if (current.autoHeight && iframe.data('ready') === 1) { + try { + if (iframe[0].contentWindow.document.location) { + inner.width( origWidth ).height(9999); + + body = iframe.contents().find('body'); + + if (scrollOut) { + body.css('overflow-x', 'hidden'); + } + + origHeight = body.outerHeight(true); + } + + } catch (e) {} + } + + } else if (current.autoWidth || current.autoHeight) { + inner.addClass( 'fancybox-tmp' ); + + // Set width or height in case we need to calculate only one dimension + if (!current.autoWidth) { + inner.width( origWidth ); + } + + if (!current.autoHeight) { + inner.height( origHeight ); + } + + if (current.autoWidth) { + origWidth = inner.width(); + } + + if (current.autoHeight) { + origHeight = inner.height(); + } + + inner.removeClass( 'fancybox-tmp' ); + } + + width = getScalar( origWidth ); + height = getScalar( origHeight ); + + ratio = origWidth / origHeight; + + // Calculations for the content + minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); + maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); + + minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); + maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); + + // These will be used to determine if wrap can fit in the viewport + origMaxWidth = maxWidth; + origMaxHeight = maxHeight; + + if (current.fitToView) { + maxWidth = Math.min(viewport.w - wSpace, maxWidth); + maxHeight = Math.min(viewport.h - hSpace, maxHeight); + } + + maxWidth_ = viewport.w - wMargin; + maxHeight_ = viewport.h - hMargin; + + if (current.aspectRatio) { + if (width > maxWidth) { + width = maxWidth; + height = getScalar(width / ratio); + } + + if (height > maxHeight) { + height = maxHeight; + width = getScalar(height * ratio); + } + + if (width < minWidth) { + width = minWidth; + height = getScalar(width / ratio); + } + + if (height < minHeight) { + height = minHeight; + width = getScalar(height * ratio); + } + + } else { + width = Math.max(minWidth, Math.min(width, maxWidth)); + + if (current.autoHeight && current.type !== 'iframe') { + inner.width( width ); + + height = inner.height(); + } + + height = Math.max(minHeight, Math.min(height, maxHeight)); + } + + // Try to fit inside viewport (including the title) + if (current.fitToView) { + inner.width( width ).height( height ); + + wrap.width( width + wPadding ); + + // Real wrap dimensions + width_ = wrap.width(); + height_ = wrap.height(); + + if (current.aspectRatio) { + while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { + if (steps++ > 19) { + break; + } + + height = Math.max(minHeight, Math.min(maxHeight, height - 10)); + width = getScalar(height * ratio); + + if (width < minWidth) { + width = minWidth; + height = getScalar(width / ratio); + } + + if (width > maxWidth) { + width = maxWidth; + height = getScalar(width / ratio); + } + + inner.width( width ).height( height ); + + wrap.width( width + wPadding ); + + width_ = wrap.width(); + height_ = wrap.height(); + } + + } else { + width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); + height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); + } + } + + if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { + width += scrollOut; + } + + inner.width( width ).height( height ); + + wrap.width( width + wPadding ); + + width_ = wrap.width(); + height_ = wrap.height(); + + canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; + canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); + + $.extend(current, { + dim : { + width : getValue( width_ ), + height : getValue( height_ ) + }, + origWidth : origWidth, + origHeight : origHeight, + canShrink : canShrink, + canExpand : canExpand, + wPadding : wPadding, + hPadding : hPadding, + wrapSpace : height_ - skin.outerHeight(true), + skinSpace : skin.height() - height + }); + + if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { + inner.height('auto'); + } + }, + + _getPosition: function (onlyAbsolute) { + var current = F.current, + viewport = F.getViewport(), + margin = current.margin, + width = F.wrap.width() + margin[1] + margin[3], + height = F.wrap.height() + margin[0] + margin[2], + rez = { + position: 'absolute', + top : margin[0], + left : margin[3] + }; + + if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { + rez.position = 'fixed'; + + } else if (!current.locked) { + rez.top += viewport.y; + rez.left += viewport.x; + } + + rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); + rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); + + return rez; + }, + + _afterZoomIn: function () { + var current = F.current; + + if (!current) { + return; + } + + F.isOpen = F.isOpened = true; + + F.wrap.css('overflow', 'visible').addClass('fancybox-opened'); + + F.update(); + + // Assign a click event + if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { + F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { + if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { + e.preventDefault(); + + F[ current.closeClick ? 'close' : 'next' ](); + } + }); + } + + // Create a close button + if (current.closeBtn) { + $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { + e.preventDefault(); + + F.close(); + }); + } + + // Create navigation arrows + if (current.arrows && F.group.length > 1) { + if (current.loop || current.index > 0) { + $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); + } + + if (current.loop || current.index < F.group.length - 1) { + $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); + } + } + + F.trigger('afterShow'); + + // Stop the slideshow if this is the last item + if (!current.loop && current.index === current.group.length - 1) { + F.play( false ); + + } else if (F.opts.autoPlay && !F.player.isActive) { + F.opts.autoPlay = false; + + F.play(); + } + }, + + _afterZoomOut: function ( obj ) { + obj = obj || F.current; + + $('.fancybox-wrap').trigger('onReset').remove(); + + $.extend(F, { + group : {}, + opts : {}, + router : false, + current : null, + isActive : false, + isOpened : false, + isOpen : false, + isClosing : false, + wrap : null, + skin : null, + outer : null, + inner : null + }); + + F.trigger('afterClose', obj); + } + }); + + /* + * Default transitions + */ + + F.transitions = { + getOrigPosition: function () { + var current = F.current, + element = current.element, + orig = current.orig, + pos = {}, + width = 50, + height = 50, + hPadding = current.hPadding, + wPadding = current.wPadding, + viewport = F.getViewport(); + + if (!orig && current.isDom && element.is(':visible')) { + orig = element.find('img:first'); + + if (!orig.length) { + orig = element; + } + } + + if (isQuery(orig)) { + pos = orig.offset(); + + if (orig.is('img')) { + width = orig.outerWidth(); + height = orig.outerHeight(); + } + + } else { + pos.top = viewport.y + (viewport.h - height) * current.topRatio; + pos.left = viewport.x + (viewport.w - width) * current.leftRatio; + } + + if (F.wrap.css('position') === 'fixed' || current.locked) { + pos.top -= viewport.y; + pos.left -= viewport.x; + } + + pos = { + top : getValue(pos.top - hPadding * current.topRatio), + left : getValue(pos.left - wPadding * current.leftRatio), + width : getValue(width + wPadding), + height : getValue(height + hPadding) + }; + + return pos; + }, + + step: function (now, fx) { + var ratio, + padding, + value, + prop = fx.prop, + current = F.current, + wrapSpace = current.wrapSpace, + skinSpace = current.skinSpace; + + if (prop === 'width' || prop === 'height') { + ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); + + if (F.isClosing) { + ratio = 1 - ratio; + } + + padding = prop === 'width' ? current.wPadding : current.hPadding; + value = now - padding; + + F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); + F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); + } + }, + + zoomIn: function () { + var current = F.current, + startPos = current.pos, + effect = current.openEffect, + elastic = effect === 'elastic', + endPos = $.extend({opacity : 1}, startPos); + + // Remove "position" property that breaks older IE + delete endPos.position; + + if (elastic) { + startPos = this.getOrigPosition(); + + if (current.openOpacity) { + startPos.opacity = 0.1; + } + + } else if (effect === 'fade') { + startPos.opacity = 0.1; + } + + F.wrap.css(startPos).animate(endPos, { + duration : effect === 'none' ? 0 : current.openSpeed, + easing : current.openEasing, + step : elastic ? this.step : null, + complete : F._afterZoomIn + }); + }, + + zoomOut: function () { + var current = F.current, + effect = current.closeEffect, + elastic = effect === 'elastic', + endPos = {opacity : 0.1}; + + if (elastic) { + endPos = this.getOrigPosition(); + + if (current.closeOpacity) { + endPos.opacity = 0.1; + } + } + + F.wrap.animate(endPos, { + duration : effect === 'none' ? 0 : current.closeSpeed, + easing : current.closeEasing, + step : elastic ? this.step : null, + complete : F._afterZoomOut + }); + }, + + changeIn: function () { + var current = F.current, + effect = current.nextEffect, + startPos = current.pos, + endPos = { opacity : 1 }, + direction = F.direction, + distance = 200, + field; + + startPos.opacity = 0.1; + + if (effect === 'elastic') { + field = direction === 'down' || direction === 'up' ? 'top' : 'left'; + + if (direction === 'down' || direction === 'right') { + startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); + endPos[ field ] = '+=' + distance + 'px'; + + } else { + startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); + endPos[ field ] = '-=' + distance + 'px'; + } + } + + // Workaround for http://bugs.jquery.com/ticket/12273 + if (effect === 'none') { + F._afterZoomIn(); + + } else { + F.wrap.css(startPos).animate(endPos, { + duration : current.nextSpeed, + easing : current.nextEasing, + complete : F._afterZoomIn + }); + } + }, + + changeOut: function () { + var previous = F.previous, + effect = previous.prevEffect, + endPos = { opacity : 0.1 }, + direction = F.direction, + distance = 200; + + if (effect === 'elastic') { + endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; + } + + previous.wrap.animate(endPos, { + duration : effect === 'none' ? 0 : previous.prevSpeed, + easing : previous.prevEasing, + complete : function () { + $(this).trigger('onReset').remove(); + } + }); + } + }; + + /* + * Overlay helper + */ + + F.helpers.overlay = { + defaults : { + closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay + speedOut : 200, // duration of fadeOut animation + showEarly : true, // indicates if should be opened immediately or wait until the content is ready + css : {}, // custom CSS properties + locked : !isTouch, // if true, the content will be locked into overlay + fixed : true // if false, the overlay CSS position property will not be set to "fixed" + }, + + overlay : null, // current handle + fixed : false, // indicates if the overlay has position "fixed" + el : $('html'), // element that contains "the lock" + + // Public methods + create : function(opts) { + opts = $.extend({}, this.defaults, opts); + + if (this.overlay) { + this.close(); + } + + this.overlay = $('
    ').appendTo( F.coming ? F.coming.parent : opts.parent ); + this.fixed = false; + + if (opts.fixed && F.defaults.fixed) { + this.overlay.addClass('fancybox-overlay-fixed'); + + this.fixed = true; + } + }, + + open : function(opts) { + var that = this; + + opts = $.extend({}, this.defaults, opts); + + if (this.overlay) { + this.overlay.unbind('.overlay').width('auto').height('auto'); + + } else { + this.create(opts); + } + + if (!this.fixed) { + W.bind('resize.overlay', $.proxy( this.update, this) ); + + this.update(); + } + + if (opts.closeClick) { + this.overlay.bind('click.overlay', function(e) { + if ($(e.target).hasClass('fancybox-overlay')) { + if (F.isActive) { + F.close(); + } else { + that.close(); + } + + return false; + } + }); + } + + this.overlay.css( opts.css ).show(); + }, + + close : function() { + var scrollV, scrollH; + + W.unbind('resize.overlay'); + + if (this.el.hasClass('fancybox-lock')) { + $('.fancybox-margin').removeClass('fancybox-margin'); + + scrollV = W.scrollTop(); + scrollH = W.scrollLeft(); + + this.el.removeClass('fancybox-lock'); + + W.scrollTop( scrollV ).scrollLeft( scrollH ); + } + + $('.fancybox-overlay').remove().hide(); + + $.extend(this, { + overlay : null, + fixed : false + }); + }, + + // Private, callbacks + + update : function () { + var width = '100%', offsetWidth; + + // Reset width/height so it will not mess + this.overlay.width(width).height('100%'); + + // jQuery does not return reliable result for IE + if (IE) { + offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); + + if (D.width() > offsetWidth) { + width = D.width(); + } + + } else if (D.width() > W.width()) { + width = D.width(); + } + + this.overlay.width(width).height(D.height()); + }, + + // This is where we can manipulate DOM, because later it would cause iframes to reload + onReady : function (opts, obj) { + var overlay = this.overlay; + + $('.fancybox-overlay').stop(true, true); + + if (!overlay) { + this.create(opts); + } + + if (opts.locked && this.fixed && obj.fixed) { + if (!overlay) { + this.margin = D.height() > W.height() ? $('html').css('margin-right').replace("px", "") : false; + } + + obj.locked = this.overlay.append( obj.wrap ); + obj.fixed = false; + } + + if (opts.showEarly === true) { + this.beforeShow.apply(this, arguments); + } + }, + + beforeShow : function(opts, obj) { + var scrollV, scrollH; + + if (obj.locked) { + if (this.margin !== false) { + $('*').filter(function(){ + return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") ); + }).addClass('fancybox-margin'); + + this.el.addClass('fancybox-margin'); + } + + scrollV = W.scrollTop(); + scrollH = W.scrollLeft(); + + this.el.addClass('fancybox-lock'); + + W.scrollTop( scrollV ).scrollLeft( scrollH ); + } + + this.open(opts); + }, + + onUpdate : function() { + if (!this.fixed) { + this.update(); + } + }, + + afterClose: function (opts) { + // Remove overlay if exists and fancyBox is not opening + // (e.g., it is not being open using afterClose callback) + //if (this.overlay && !F.isActive) { + if (this.overlay && !F.coming) { + this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); + } + } + }; + + /* + * Title helper + */ + + F.helpers.title = { + defaults : { + type : 'float', // 'float', 'inside', 'outside' or 'over', + position : 'bottom' // 'top' or 'bottom' + }, + + beforeShow: function (opts) { + var current = F.current, + text = current.title, + type = opts.type, + title, + target; + + if ($.isFunction(text)) { + text = text.call(current.element, current); + } + + if (!isString(text) || $.trim(text) === '') { + return; + } + + title = $('
    ' + text + '
    '); + + switch (type) { + case 'inside': + target = F.skin; + break; + + case 'outside': + target = F.wrap; + break; + + case 'over': + target = F.inner; + break; + + default: // 'float' + target = F.skin; + + title.appendTo('body'); + + if (IE) { + title.width( title.width() ); + } + + title.wrapInner(''); + + //Increase bottom margin so this title will also fit into viewport + F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); + break; + } + + title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); + } + }; + + // jQuery plugin initialization + $.fn.fancybox = function (options) { + var index, + that = $(this), + selector = this.selector || '', + run = function(e) { + var what = $(this).blur(), idx = index, relType, relVal; + + if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { + relType = options.groupAttr || 'data-fancybox-group'; + relVal = what.attr(relType); + + if (!relVal) { + relType = 'rel'; + relVal = what.get(0)[ relType ]; + } + + if (relVal && relVal !== '' && relVal !== 'nofollow') { + what = selector.length ? $(selector) : that; + what = what.filter('[' + relType + '="' + relVal + '"]'); + idx = what.index(this); + } + + options.index = idx; + + // Stop an event from bubbling if everything is fine + if (F.open(what, options) !== false) { + e.preventDefault(); + } + } + }; + + options = options || {}; + index = options.index || 0; + + if (!selector || options.live === false) { + that.unbind('click.fb-start').bind('click.fb-start', run); + + } else { + D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); + } + + this.filter('[data-fancybox-start=1]').trigger('click'); + + return this; + }; + + // Tests that need a body at doc ready + D.ready(function() { + var w1, w2; + + if ( $.scrollbarWidth === undefined ) { + // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth + $.scrollbarWidth = function() { + var parent = $('
    ').appendTo('body'), + child = parent.children(), + width = child.innerWidth() - child.height( 99 ).innerWidth(); + + parent.remove(); + + return width; + }; + } + + if ( $.support.fixedPosition === undefined ) { + $.support.fixedPosition = (function() { + var elem = $('
    ').appendTo('body'), + fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); + + elem.remove(); + + return fixed; + }()); + } + + $.extend(F.defaults, { + scrollbarWidth : $.scrollbarWidth(), + fixed : $.support.fixedPosition, + parent : $('body') + }); + + //Get real width of page scroll-bar + w1 = $(window).width(); + + H.addClass('fancybox-lock-test'); + + w2 = $(window).width(); + + H.removeClass('fancybox-lock-test'); + + $("").appendTo("head"); + }); + +}(window, document, jQuery)); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.pack.js b/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.pack.js new file mode 100644 index 0000000..73f7578 --- /dev/null +++ b/plugins/web_gui/static/plugins/fancybox/jquery.fancybox.pack.js @@ -0,0 +1,46 @@ +/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ +(function(r,G,f,v){var J=f("html"),n=f(r),p=f(G),b=f.fancybox=function(){b.open.apply(this,arguments)},I=navigator.userAgent.match(/msie/i),B=null,s=G.createTouch!==v,t=function(a){return a&&a.hasOwnProperty&&a instanceof f},q=function(a){return a&&"string"===f.type(a)},E=function(a){return q(a)&&0
    ',image:'',iframe:'",error:'

    The requested content cannot be loaded.
    Please try again later.

    ',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, +openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, +isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=t(a)?f(a).get():[a]),f.each(a,function(e,c){var k={},g,h,j,m,l;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),t(c)?(k={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0,k, +c.metadata())):k=c);g=d.href||k.href||(q(c)?c:null);h=d.title!==v?d.title:k.title||"";m=(j=d.content||k.content)?"html":d.type||k.type;!m&&k.isDom&&(m=c.data("fancybox-type"),m||(m=(m=c.prop("class").match(/fancybox\.(\w+)/))?m[1]:null));q(g)&&(m||(b.isImage(g)?m="image":b.isSWF(g)?m="swf":"#"===g.charAt(0)?m="inline":q(c)&&(m="html",j=c)),"ajax"===m&&(l=g.split(/\s+/,2),g=l.shift(),l=l.shift()));j||("inline"===m?g?j=f(q(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):k.isDom&&(j=c):"html"===m?j=g:!m&&(!g&& +k.isDom)&&(m="inline",j=c));f.extend(k,{href:g,type:m,content:j,title:h,selector:l});a[e]=k}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==v&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current|| +b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer= +setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==v&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,k;c&&(k=b._getPosition(d),a&&"scroll"===a.type?(delete k.position,c.stop(!0,!0).animate(k,200)):(c.css(k),e.pos=f.extend({},e.dim,k)))},update:function(a){var d= +a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(B),B=null);b.isOpen&&!B&&(B=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),B=null)},e&&!s?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,s&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"),b.trigger("onUpdate")), +b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
    ').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked||!1,d={x:n.scrollLeft(), +y:n.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=s&&r.innerWidth?r.innerWidth:n.width(),d.h=s&&r.innerHeight?r.innerHeight:n.height());return d},unbindEvents:function(){b.wrap&&t(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");n.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(n.bind("orientationchange.fb"+(s?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c=e.which||e.keyCode,k=e.target||e.srcElement; +if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!k||!k.type&&!f(k).is("[contenteditable]")))&&f.each(d,function(d,k){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!j&&1g||0>k)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&&b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0, +{},b.helpers[d].defaults,e),c)});p.trigger(a)}},isImage:function(a){return q(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return q(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=l(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1, +mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio= +!0);"iframe"===c&&s&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(s?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,w(d.padding[a]))});b.trigger("onReady");if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href"); +"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width=this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload= +this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",s?"auto":a.iframe.scrolling).attr("src",a.href); +f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);s||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload, +e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,k,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents();e=a.content;c=a.type;k=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin, +outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
    ").html(e).find(a.selector):t(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
    ').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder",!1)}));break;case "image":e=a.tpl.image.replace("{href}", +g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}(!t(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow");a.inner.css("overflow","yes"===k?"scroll": +"no"===k?"hidden":k);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,k=b.skin,g=b.inner,h=b.current,c=h.width,j=h.height,m=h.minWidth,u=h.minHeight,n=h.maxWidth,p=h.maxHeight,s=h.scrolling,q=h.scrollOutside? +h.scrollbarWidth:0,x=h.margin,y=l(x[1]+x[3]),r=l(x[0]+x[2]),v,z,t,C,A,F,B,D,H;e.add(k).add(g).width("auto").height("auto").removeClass("fancybox-tmp");x=l(k.outerWidth(!0)-k.width());v=l(k.outerHeight(!0)-k.height());z=y+x;t=r+v;C=E(c)?(a.w-z)*l(c)/100:c;A=E(j)?(a.h-t)*l(j)/100:j;if("iframe"===h.type){if(H=h.content,h.autoHeight&&1===H.data("ready"))try{H[0].contentWindow.document.location&&(g.width(C).height(9999),F=H.contents().find("body"),q&&F.css("overflow-x","hidden"),A=F.outerHeight(!0))}catch(G){}}else if(h.autoWidth|| +h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=l(C);j=l(A);D=C/A;m=l(E(m)?l(m,"w")-z:m);n=l(E(n)?l(n,"w")-z:n);u=l(E(u)?l(u,"h")-t:u);p=l(E(p)?l(p,"h")-t:p);F=n;B=p;h.fitToView&&(n=Math.min(a.w-z,n),p=Math.min(a.h-t,p));z=a.w-y;r=a.h-r;h.aspectRatio?(c>n&&(c=n,j=l(c/D)),j>p&&(j=p,c=l(j*D)),cz||y>r)&&(c>m&&j>u)&&!(19n&&(c=n,j=l(c/D)),g.width(c).height(j),e.width(c+x),a=e.width(),y=e.height();else c=Math.max(m,Math.min(c,c-(a-z))),j=Math.max(u,Math.min(j,j-(y-r)));q&&("auto"===s&&jz||y>r)&&c>m&&j>u;c=h.aspectRatio?cu&&j
    ').appendTo(b.coming?b.coming.parent:a.parent);this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(n.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive? +b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){var a,b;n.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),a=n.scrollTop(),b=n.scrollLeft(),this.el.removeClass("fancybox-lock"),n.scrollTop(a).scrollLeft(b));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%");I?(b=Math.max(G.documentElement.offsetWidth,G.body.offsetWidth), +p.width()>b&&(a=p.width())):p.width()>n.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&(this.fixed&&b.fixed)&&(e||(this.margin=p.height()>n.height()?f("html").css("margin-right").replace("px",""):!1),b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){var e,c;b.locked&&(!1!==this.margin&&(f("*").filter(function(){return"fixed"=== +f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin")),e=n.scrollTop(),c=n.scrollLeft(),this.el.addClass("fancybox-lock"),n.scrollTop(e).scrollLeft(c));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d= +b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(q(e)&&""!==f.trim(e)){d=f('
    '+e+"
    ");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),I&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(l(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d, +e=f(this),c=this.selector||"",k=function(g){var h=f(this).blur(),j=d,k,l;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(k=a.groupAttr||"data-fancybox-group",l=h.attr(k),l||(k="rel",l=h.get(0)[k]),l&&(""!==l&&"nofollow"!==l)&&(h=c.length?f(c):e,h=h.filter("["+k+'="'+l+'"]'),j=h.index(this)),a.index=j,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",k):p.undelegate(c,"click.fb-start").delegate(c+ +":not('.fancybox-item, .fancybox-nav')","click.fb-start",k);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===v&&(f.scrollbarWidth=function(){var a=f('
    ').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===v){a=f.support;d=f('
    ').appendTo("body");var e=20=== +d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(r).width();J.addClass("fancybox-lock-test");d=f(r).width();J.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/fineuploader/LICENSE b/plugins/web_gui/static/plugins/fineuploader/LICENSE new file mode 100644 index 0000000..4e1208a --- /dev/null +++ b/plugins/web_gui/static/plugins/fineuploader/LICENSE @@ -0,0 +1,676 @@ +Fine Uploader is licensed under GNU GPL version 3: + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/plugins/web_gui/static/plugins/fineuploader/edit.gif b/plugins/web_gui/static/plugins/fineuploader/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..13aa89a3463729ae6987f84f65afae13d07dcf37 GIT binary patch literal 145 zcmZ?wbhEHb7VX+#JX#3zK3=Gx)NBT74 literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.css b/plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.css new file mode 100644 index 0000000..812f873 --- /dev/null +++ b/plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.css @@ -0,0 +1,205 @@ +/*! +* Fine Uploader +* +* Copyright 2013, Widen Enterprises, Inc. info@fineuploader.com +* +* Version: 4.3.1 +* +* Homepage: http://fineuploader.com +* +* Repository: git://github.com/Widen/fine-uploader.git +* +* Licensed under GNU GPL v3, see LICENSE +*/ + + +.qq-uploader { + position: relative; + width: 100%; +} +.qq-upload-button { + display: block; + width: 105px; + padding: 7px 0; + text-align: center; + background: #880000; + border-bottom: 1px solid #DDD; + color: #FFF; +} +.qq-upload-button-hover { + background: #CC0000; +} +.qq-upload-button-focus { + outline: 1px dotted #000000; +} +.qq-upload-drop-area, .qq-upload-extra-drop-area { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + min-height: 30px; + z-index: 2; + background: #FF9797; + text-align: center; +} +.qq-upload-drop-area span { + display: block; + position: absolute; + top: 50%; + width: 100%; + margin-top: -8px; + font-size: 16px; +} +.qq-upload-extra-drop-area { + position: relative; + margin-top: 50px; + font-size: 16px; + padding-top: 30px; + height: 20px; + min-height: 40px; +} +.qq-upload-drop-area-active { + background: #FF7171; +} +.qq-upload-list { + margin: 0; + padding: 0; + list-style: none; +} +.qq-upload-list li { + margin: 0; + padding: 9px; + line-height: 15px; + font-size: 16px; + background-color: #FFF0BD; +} +.qq-upload-file, .qq-upload-spinner, .qq-upload-size, +.qq-upload-cancel, .qq-upload-retry, .qq-upload-failed-text, +.qq-upload-delete, .qq-upload-pause, .qq-upload-continue { + margin-right: 12px; + display: inline; +} +.qq-upload-file { +} +.qq-upload-spinner { + display: inline-block; + background: url("loading.gif"); + width: 15px; + height: 15px; + vertical-align: text-bottom; +} +.qq-drop-processing { + display: block; +} +.qq-drop-processing-spinner { + display: inline-block; + background: url("processing.gif"); + width: 24px; + height: 24px; + vertical-align: text-bottom; +} + +.qq-upload-delete, .qq-upload-pause, .qq-upload-continue { + display: inline; +} + +.qq-upload-retry, .qq-upload-delete, .qq-upload-cancel, +.qq-upload-pause, .qq-upload-continue { + color: #000000; +} + +.qq-upload-retryable .qq-upload-retry { + display: inline; +} +.qq-upload-size, .qq-upload-cancel, .qq-upload-retry, +.qq-upload-delete, .qq-upload-pause, .qq-upload-continue { + font-size: 12px; + font-weight: normal; +} +.qq-upload-failed-text { + display: none; + font-style: italic; + font-weight: bold; +} +.qq-upload-failed-icon { + display:none; + width:15px; + height:15px; + vertical-align:text-bottom; +} +.qq-upload-fail .qq-upload-failed-text { + display: inline; +} +.qq-upload-retrying .qq-upload-failed-text { + display: inline; + color: #D60000; +} +.qq-upload-list li.qq-upload-success { + background-color: #5DA30C; + color: #FFFFFF; +} +.qq-upload-list li.qq-upload-fail { + background-color: #D60000; + color: #FFFFFF; +} +.qq-progress-bar { + display: block; + background: -moz-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%, rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(30,87,153,1)), color-stop(50%,rgba(41,137,216,1)), color-stop(51%,rgba(32,124,202,1)), color-stop(100%,rgba(125,185,232,1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(30,87,153,1) 0%,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%); /* W3C */ + width: 0%; + height: 15px; + border-radius: 6px; + margin-bottom: 3px; +} + +INPUT.qq-edit-filename { + position: absolute; + opacity: 0; + filter: alpha(opacity=0); + z-index: -1; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; +} + +.qq-upload-file.qq-editable { + cursor: pointer; +} + +.qq-edit-filename-icon.qq-editable { + display: inline-block; + cursor: pointer; +} + +INPUT.qq-edit-filename.qq-editing { + position: static; + margin-top: -5px; + margin-right: 10px; + margin-bottom: -5px; + + opacity: 1; + filter: alpha(opacity=100); + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; +} + +.qq-edit-filename-icon { + display: none; + background: url("edit.gif"); + width: 15px; + height: 15px; + vertical-align: text-bottom; + margin-right: 5px; +} + +INPUT.qq-edit-filename.qq-editing ~ .qq-upload-cancel { + display: none; +} + +.qq-hide { + display: none; +} + +/*! 2014-02-16 */ diff --git a/plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.min.css b/plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.min.css new file mode 100644 index 0000000..862b6ee --- /dev/null +++ b/plugins/web_gui/static/plugins/fineuploader/fineuploader-4.3.1.min.css @@ -0,0 +1,19 @@ +/*! +* Fine Uploader +* +* Copyright 2013, Widen Enterprises, Inc. info@fineuploader.com +* +* Version: 4.3.1 +* +* Homepage: http://fineuploader.com +* +* Repository: git://github.com/Widen/fine-uploader.git +* +* Licensed under GNU GPL v3, see LICENSE +*/ + + +/*! fineuploader 2014-02-16 */ + +.qq-uploader{position:relative;width:100%}.qq-upload-button{display:block;width:105px;padding:7px 0;text-align:center;background:#800;border-bottom:1px solid #DDD;color:#FFF}.qq-upload-button-hover{background:#C00}.qq-upload-button-focus{outline:1px dotted #000}.qq-upload-drop-area,.qq-upload-extra-drop-area{position:absolute;top:0;left:0;width:100%;height:100%;min-height:30px;z-index:2;background:#FF9797;text-align:center}.qq-upload-drop-area span{display:block;position:absolute;top:50%;width:100%;margin-top:-8px;font-size:16px}.qq-upload-extra-drop-area{position:relative;margin-top:50px;font-size:16px;padding-top:30px;height:20px;min-height:40px}.qq-upload-drop-area-active{background:#FF7171}.qq-upload-list{margin:0;padding:0;list-style:none}.qq-upload-list li{margin:0;padding:9px;line-height:15px;font-size:16px;background-color:#FFF0BD}.qq-upload-file,.qq-upload-spinner,.qq-upload-size,.qq-upload-cancel,.qq-upload-retry,.qq-upload-failed-text,.qq-upload-delete,.qq-upload-pause,.qq-upload-continue{margin-right:12px;display:inline}.qq-upload-file{}.qq-upload-spinner{display:inline-block;background:url(loading.gif);width:15px;height:15px;vertical-align:text-bottom}.qq-drop-processing{display:block}.qq-drop-processing-spinner{display:inline-block;background:url(processing.gif);width:24px;height:24px;vertical-align:text-bottom}.qq-upload-delete,.qq-upload-pause,.qq-upload-continue{display:inline}.qq-upload-retry,.qq-upload-delete,.qq-upload-cancel,.qq-upload-pause,.qq-upload-continue{color:#000}.qq-upload-retryable .qq-upload-retry{display:inline}.qq-upload-size,.qq-upload-cancel,.qq-upload-retry,.qq-upload-delete,.qq-upload-pause,.qq-upload-continue{font-size:12px;font-weight:400}.qq-upload-failed-text{display:none;font-style:italic;font-weight:700}.qq-upload-failed-icon{display:none;width:15px;height:15px;vertical-align:text-bottom}.qq-upload-fail .qq-upload-failed-text{display:inline}.qq-upload-retrying .qq-upload-failed-text{display:inline;color:#D60000}.qq-upload-list li.qq-upload-success{background-color:#5DA30C;color:#FFF}.qq-upload-list li.qq-upload-fail{background-color:#D60000;color:#FFF}.qq-progress-bar{display:block;background:-moz-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,rgba(30,87,153,1)),color-stop(50%,rgba(41,137,216,1)),color-stop(51%,rgba(32,124,202,1)),color-stop(100%,rgba(125,185,232,1)));background:-webkit-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-o-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:-ms-linear-gradient(top,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);background:linear-gradient(to bottom,rgba(30,87,153,1) 0,rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%,rgba(125,185,232,1) 100%);width:0;height:15px;border-radius:6px;margin-bottom:3px}INPUT.qq-edit-filename{position:absolute;opacity:0;filter:alpha(opacity=0);z-index:-1;-ms-filter:"alpha(Opacity=0)"}.qq-upload-file.qq-editable{cursor:pointer}.qq-edit-filename-icon.qq-editable{display:inline-block;cursor:pointer}INPUT.qq-edit-filename.qq-editing{position:static;margin-top:-5px;margin-right:10px;margin-bottom:-5px;opacity:1;filter:alpha(opacity=100);-ms-filter:"alpha(Opacity=100)"}.qq-edit-filename-icon{display:none;background:url(edit.gif);width:15px;height:15px;vertical-align:text-bottom;margin-right:5px}INPUT.qq-edit-filename.qq-editing~.qq-upload-cancel{display:none}.qq-hide{display:none} +/*! 2014-02-16 */ diff --git a/plugins/web_gui/static/plugins/fineuploader/iframe.xss.response-4.3.1.js b/plugins/web_gui/static/plugins/fineuploader/iframe.xss.response-4.3.1.js new file mode 100644 index 0000000..e2cc119 --- /dev/null +++ b/plugins/web_gui/static/plugins/fineuploader/iframe.xss.response-4.3.1.js @@ -0,0 +1,7 @@ +(function() { + "use strict"; + var match = /(\{.*\})/.exec(document.body.innerHTML); + if (match) { + parent.postMessage(match[1], "*"); + } +}()); diff --git a/plugins/web_gui/static/plugins/fineuploader/jquery.fineuploader-4.3.1.js b/plugins/web_gui/static/plugins/fineuploader/jquery.fineuploader-4.3.1.js new file mode 100644 index 0000000..3ce7601 --- /dev/null +++ b/plugins/web_gui/static/plugins/fineuploader/jquery.fineuploader-4.3.1.js @@ -0,0 +1,9228 @@ +/*! +* Fine Uploader +* +* Copyright 2013, Widen Enterprises, Inc. info@fineuploader.com +* +* Version: 4.3.1 +* +* Homepage: http://fineuploader.com +* +* Repository: git://github.com/Widen/fine-uploader.git +* +* Licensed under GNU GPL v3, see LICENSE +*/ + + +/*globals window, navigator, document, FormData, File, HTMLInputElement, XMLHttpRequest, Blob, Storage, ActiveXObject */ +var qq = function(element) { + "use strict"; + + return { + hide: function() { + element.style.display = "none"; + return this; + }, + + /** Returns the function which detaches attached event */ + attach: function(type, fn) { + if (element.addEventListener){ + element.addEventListener(type, fn, false); + } else if (element.attachEvent){ + element.attachEvent("on" + type, fn); + } + return function() { + qq(element).detach(type, fn); + }; + }, + + detach: function(type, fn) { + if (element.removeEventListener){ + element.removeEventListener(type, fn, false); + } else if (element.attachEvent){ + element.detachEvent("on" + type, fn); + } + return this; + }, + + contains: function(descendant) { + // The [W3C spec](http://www.w3.org/TR/domcore/#dom-node-contains) + // says a `null` (or ostensibly `undefined`) parameter + // passed into `Node.contains` should result in a false return value. + // IE7 throws an exception if the parameter is `undefined` though. + if (!descendant) { + return false; + } + + // compareposition returns false in this case + if (element === descendant) { + return true; + } + + if (element.contains){ + return element.contains(descendant); + } else { + /*jslint bitwise: true*/ + return !!(descendant.compareDocumentPosition(element) & 8); + } + }, + + /** + * Insert this element before elementB. + */ + insertBefore: function(elementB) { + elementB.parentNode.insertBefore(element, elementB); + return this; + }, + + remove: function() { + element.parentNode.removeChild(element); + return this; + }, + + /** + * Sets styles for an element. + * Fixes opacity in IE6-8. + */ + css: function(styles) { + /*jshint eqnull: true*/ + if (element.style == null) { + throw new qq.Error("Can't apply style to node as it is not on the HTMLElement prototype chain!"); + } + + /*jshint -W116*/ + if (styles.opacity != null){ + if (typeof element.style.opacity !== "string" && typeof(element.filters) !== "undefined"){ + styles.filter = "alpha(opacity=" + Math.round(100 * styles.opacity) + ")"; + } + } + qq.extend(element.style, styles); + + return this; + }, + + hasClass: function(name) { + var re = new RegExp("(^| )" + name + "( |$)"); + return re.test(element.className); + }, + + addClass: function(name) { + if (!qq(element).hasClass(name)){ + element.className += " " + name; + } + return this; + }, + + removeClass: function(name) { + var re = new RegExp("(^| )" + name + "( |$)"); + element.className = element.className.replace(re, " ").replace(/^\s+|\s+$/g, ""); + return this; + }, + + getByClass: function(className) { + var candidates, + result = []; + + if (element.querySelectorAll){ + return element.querySelectorAll("." + className); + } + + candidates = element.getElementsByTagName("*"); + + qq.each(candidates, function(idx, val) { + if (qq(val).hasClass(className)){ + result.push(val); + } + }); + return result; + }, + + children: function() { + var children = [], + child = element.firstChild; + + while (child){ + if (child.nodeType === 1){ + children.push(child); + } + child = child.nextSibling; + } + + return children; + }, + + setText: function(text) { + element.innerText = text; + element.textContent = text; + return this; + }, + + clearText: function() { + return qq(element).setText(""); + }, + + // Returns true if the attribute exists on the element + // AND the value of the attribute is NOT "false" (case-insensitive) + hasAttribute: function(attrName) { + var attrVal; + + if (element.hasAttribute) { + + if (!element.hasAttribute(attrName)) { + return false; + } + + /*jshint -W116*/ + return (/^false$/i).exec(element.getAttribute(attrName)) == null; + } + else { + attrVal = element[attrName]; + + if (attrVal === undefined) { + return false; + } + + /*jshint -W116*/ + return (/^false$/i).exec(attrVal) == null; + } + } + }; +}; + +(function(){ + "use strict"; + + qq.log = function(message, level) { + if (window.console) { + if (!level || level === "info") { + window.console.log(message); + } + else + { + if (window.console[level]) { + window.console[level](message); + } + else { + window.console.log("<" + level + "> " + message); + } + } + } + }; + + qq.isObject = function(variable) { + return variable && !variable.nodeType && Object.prototype.toString.call(variable) === "[object Object]"; + }; + + qq.isFunction = function(variable) { + return typeof(variable) === "function"; + }; + + /** + * Check the type of a value. Is it an "array"? + * + * @param value value to test. + * @returns true if the value is an array or associated with an `ArrayBuffer` + */ + qq.isArray = function(value) { + return Object.prototype.toString.call(value) === "[object Array]" || + (value && window.ArrayBuffer && value.buffer && value.buffer.constructor === ArrayBuffer); + }; + + // Looks for an object on a `DataTransfer` object that is associated with drop events when utilizing the Filesystem API. + qq.isItemList = function(maybeItemList) { + return Object.prototype.toString.call(maybeItemList) === "[object DataTransferItemList]"; + }; + + // Looks for an object on a `NodeList` or an `HTMLCollection`|`HTMLFormElement`|`HTMLSelectElement` + // object that is associated with collections of Nodes. + qq.isNodeList = function(maybeNodeList) { + return Object.prototype.toString.call(maybeNodeList) === "[object NodeList]" || + // If `HTMLCollection` is the actual type of the object, we must determine this + // by checking for expected properties/methods on the object + (maybeNodeList.item && maybeNodeList.namedItem); + }; + + qq.isString = function(maybeString) { + return Object.prototype.toString.call(maybeString) === "[object String]"; + }; + + qq.trimStr = function(string) { + if (String.prototype.trim) { + return string.trim(); + } + + return string.replace(/^\s+|\s+$/g,""); + }; + + + /** + * @param str String to format. + * @returns {string} A string, swapping argument values with the associated occurrence of {} in the passed string. + */ + qq.format = function(str) { + + var args = Array.prototype.slice.call(arguments, 1), + newStr = str, + nextIdxToReplace = newStr.indexOf("{}"); + + qq.each(args, function(idx, val) { + var strBefore = newStr.substring(0, nextIdxToReplace), + strAfter = newStr.substring(nextIdxToReplace+2); + + newStr = strBefore + val + strAfter; + nextIdxToReplace = newStr.indexOf("{}", nextIdxToReplace + val.length); + + // End the loop if we have run out of tokens (when the arguments exceed the # of tokens) + if (nextIdxToReplace < 0) { + return false; + } + }); + + return newStr; + }; + + qq.isFile = function(maybeFile) { + return window.File && Object.prototype.toString.call(maybeFile) === "[object File]"; + }; + + qq.isFileList = function(maybeFileList) { + return window.FileList && Object.prototype.toString.call(maybeFileList) === "[object FileList]"; + }; + + qq.isFileOrInput = function(maybeFileOrInput) { + return qq.isFile(maybeFileOrInput) || qq.isInput(maybeFileOrInput); + }; + + qq.isInput = function(maybeInput, notFile) { + var evaluateType = function(type) { + var normalizedType = type.toLowerCase(); + + if (notFile) { + return normalizedType !== "file"; + } + + return normalizedType === "file"; + }; + + if (window.HTMLInputElement) { + if (Object.prototype.toString.call(maybeInput) === "[object HTMLInputElement]") { + if (maybeInput.type && evaluateType(maybeInput.type)) { + return true; + } + } + } + if (maybeInput.tagName) { + if (maybeInput.tagName.toLowerCase() === "input") { + if (maybeInput.type && evaluateType(maybeInput.type)) { + return true; + } + } + } + + return false; + }; + + qq.isBlob = function(maybeBlob) { + return window.Blob && Object.prototype.toString.call(maybeBlob) === "[object Blob]"; + }; + + qq.isXhrUploadSupported = function() { + var input = document.createElement("input"); + input.type = "file"; + + return ( + input.multiple !== undefined && + typeof File !== "undefined" && + typeof FormData !== "undefined" && + typeof (qq.createXhrInstance()).upload !== "undefined" ); + }; + + // Fall back to ActiveX is native XHR is disabled (possible in any version of IE). + qq.createXhrInstance = function() { + if (window.XMLHttpRequest) { + return new XMLHttpRequest(); + } + + try { + return new ActiveXObject("MSXML2.XMLHTTP.3.0"); + } + catch(error) { + qq.log("Neither XHR or ActiveX are supported!", "error"); + return null; + } + }; + + qq.isFolderDropSupported = function(dataTransfer) { + return (dataTransfer.items && dataTransfer.items[0].webkitGetAsEntry); + }; + + qq.isFileChunkingSupported = function() { + return !qq.android() && //android's impl of Blob.slice is broken + qq.isXhrUploadSupported() && + (File.prototype.slice !== undefined || File.prototype.webkitSlice !== undefined || File.prototype.mozSlice !== undefined); + }; + + qq.sliceBlob = function(fileOrBlob, start, end) { + var slicer = fileOrBlob.slice || fileOrBlob.mozSlice || fileOrBlob.webkitSlice; + + return slicer.call(fileOrBlob, start, end); + }; + + qq.arrayBufferToHex = function(buffer) { + var bytesAsHex = "", + bytes = new Uint8Array(buffer); + + + qq.each(bytes, function(idx, byte) { + var byteAsHexStr = byte.toString(16); + + if (byteAsHexStr.length < 2) { + byteAsHexStr = "0" + byteAsHexStr; + } + + bytesAsHex += byteAsHexStr; + }); + + return bytesAsHex; + }; + + qq.readBlobToHex = function(blob, startOffset, length) { + var initialBlob = qq.sliceBlob(blob, startOffset, startOffset + length), + fileReader = new FileReader(), + promise = new qq.Promise(); + + fileReader.onload = function() { + promise.success(qq.arrayBufferToHex(fileReader.result)); + }; + + fileReader.readAsArrayBuffer(initialBlob); + + return promise; + }; + + qq.extend = function(first, second, extendNested) { + qq.each(second, function(prop, val) { + if (extendNested && qq.isObject(val)) { + if (first[prop] === undefined) { + first[prop] = {}; + } + qq.extend(first[prop], val, true); + } + else { + first[prop] = val; + } + }); + + return first; + }; + + /** + * Allow properties in one object to override properties in another, + * keeping track of the original values from the target object. + * + * Note that the pre-overriden properties to be overriden by the source will be passed into the `sourceFn` when it is invoked. + * + * @param target Update properties in this object from some source + * @param sourceFn A function that, when invoked, will return properties that will replace properties with the same name in the target. + * @returns {object} The target object + */ + qq.override = function(target, sourceFn) { + var super_ = {}, + source = sourceFn(super_); + + qq.each(source, function(srcPropName, srcPropVal) { + if (target[srcPropName] !== undefined) { + super_[srcPropName] = target[srcPropName]; + } + + target[srcPropName] = srcPropVal; + }); + + return target; + }; + + /** + * Searches for a given element in the array, returns -1 if it is not present. + * @param {Number} [from] The index at which to begin the search + */ + qq.indexOf = function(arr, elt, from){ + if (arr.indexOf) { + return arr.indexOf(elt, from); + } + + from = from || 0; + var len = arr.length; + + if (from < 0) { + from += len; + } + + for (; from < len; from+=1){ + if (arr.hasOwnProperty(from) && arr[from] === elt){ + return from; + } + } + return -1; + }; + + //this is a version 4 UUID + qq.getUniqueId = function(){ + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { + /*jslint eqeq: true, bitwise: true*/ + var r = Math.random()*16|0, v = c == "x" ? r : (r&0x3|0x8); + return v.toString(16); + }); + }; + + // + // Browsers and platforms detection + + qq.ie = function(){ + return navigator.userAgent.indexOf("MSIE") !== -1; + }; + qq.ie7 = function(){ + return navigator.userAgent.indexOf("MSIE 7") !== -1; + }; + qq.ie10 = function(){ + return navigator.userAgent.indexOf("MSIE 10") !== -1; + }; + qq.ie11 = function(){ + return (navigator.userAgent.indexOf("Trident") !== -1 && + navigator.userAgent.indexOf("rv:11") !== -1); + }; + qq.safari = function(){ + return navigator.vendor !== undefined && navigator.vendor.indexOf("Apple") !== -1; + }; + qq.chrome = function(){ + return navigator.vendor !== undefined && navigator.vendor.indexOf("Google") !== -1; + }; + qq.opera = function(){ + return navigator.vendor !== undefined && navigator.vendor.indexOf("Opera") !== -1; + }; + qq.firefox = function(){ + return (!qq.ie11() && navigator.userAgent.indexOf("Mozilla") !== -1 && navigator.vendor !== undefined && navigator.vendor === ""); + }; + qq.windows = function(){ + return navigator.platform === "Win32"; + }; + qq.android = function(){ + return navigator.userAgent.toLowerCase().indexOf("android") !== -1; + }; + qq.ios7 = function() { + return qq.ios() && navigator.userAgent.indexOf(" OS 7_") !== -1; + }; + qq.ios = function() { + /*jshint -W014 */ + return navigator.userAgent.indexOf("iPad") !== -1 + || navigator.userAgent.indexOf("iPod") !== -1 + || navigator.userAgent.indexOf("iPhone") !== -1; + }; + + // + // Events + + qq.preventDefault = function(e){ + if (e.preventDefault){ + e.preventDefault(); + } else{ + e.returnValue = false; + } + }; + + /** + * Creates and returns element from html string + * Uses innerHTML to create an element + */ + qq.toElement = (function(){ + var div = document.createElement("div"); + return function(html){ + div.innerHTML = html; + var element = div.firstChild; + div.removeChild(element); + return element; + }; + }()); + + //key and value are passed to callback for each entry in the iterable item + qq.each = function(iterableItem, callback) { + var keyOrIndex, retVal; + + if (iterableItem) { + // Iterate through [`Storage`](http://www.w3.org/TR/webstorage/#the-storage-interface) items + if (window.Storage && iterableItem.constructor === window.Storage) { + for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) { + retVal = callback(iterableItem.key(keyOrIndex), iterableItem.getItem(iterableItem.key(keyOrIndex))); + if (retVal === false) { + break; + } + } + } + // `DataTransferItemList` & `NodeList` objects are array-like and should be treated as arrays + // when iterating over items inside the object. + else if (qq.isArray(iterableItem) || qq.isItemList(iterableItem) || qq.isNodeList(iterableItem)) { + for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) { + retVal = callback(keyOrIndex, iterableItem[keyOrIndex]); + if (retVal === false) { + break; + } + } + } + else if (qq.isString(iterableItem)) { + for (keyOrIndex = 0; keyOrIndex < iterableItem.length; keyOrIndex++) { + retVal = callback(keyOrIndex, iterableItem.charAt(keyOrIndex)); + if (retVal === false) { + break; + } + } + } + else { + for (keyOrIndex in iterableItem) { + if (Object.prototype.hasOwnProperty.call(iterableItem, keyOrIndex)) { + retVal = callback(keyOrIndex, iterableItem[keyOrIndex]); + if (retVal === false) { + break; + } + } + } + } + } + }; + + //include any args that should be passed to the new function after the context arg + qq.bind = function(oldFunc, context) { + if (qq.isFunction(oldFunc)) { + var args = Array.prototype.slice.call(arguments, 2); + + return function() { + var newArgs = qq.extend([], args); + if (arguments.length) { + newArgs = newArgs.concat(Array.prototype.slice.call(arguments)); + } + return oldFunc.apply(context, newArgs); + }; + } + + throw new Error("first parameter must be a function!"); + }; + + /** + * obj2url() takes a json-object as argument and generates + * a querystring. pretty much like jQuery.param() + * + * how to use: + * + * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');` + * + * will result in: + * + * `http://any.url/upload?otherParam=value&a=b&c=d` + * + * @param Object JSON-Object + * @param String current querystring-part + * @return String encoded querystring + */ + qq.obj2url = function(obj, temp, prefixDone){ + /*jshint laxbreak: true*/ + var uristrings = [], + prefix = "&", + add = function(nextObj, i){ + var nextTemp = temp + ? (/\[\]$/.test(temp)) // prevent double-encoding + ? temp + : temp+"["+i+"]" + : i; + if ((nextTemp !== "undefined") && (i !== "undefined")) { + uristrings.push( + (typeof nextObj === "object") + ? qq.obj2url(nextObj, nextTemp, true) + : (Object.prototype.toString.call(nextObj) === "[object Function]") + ? encodeURIComponent(nextTemp) + "=" + encodeURIComponent(nextObj()) + : encodeURIComponent(nextTemp) + "=" + encodeURIComponent(nextObj) + ); + } + }; + + if (!prefixDone && temp) { + prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? "" : "&" : "?"; + uristrings.push(temp); + uristrings.push(qq.obj2url(obj)); + } else if ((Object.prototype.toString.call(obj) === "[object Array]") && (typeof obj !== "undefined") ) { + qq.each(obj, function(idx, val) { + add(val, idx); + }); + } else if ((typeof obj !== "undefined") && (obj !== null) && (typeof obj === "object")){ + qq.each(obj, function(prop, val) { + add(val, prop); + }); + } else { + uristrings.push(encodeURIComponent(temp) + "=" + encodeURIComponent(obj)); + } + + if (temp) { + return uristrings.join(prefix); + } else { + return uristrings.join(prefix) + .replace(/^&/, "") + .replace(/%20/g, "+"); + } + }; + + qq.obj2FormData = function(obj, formData, arrayKeyName) { + if (!formData) { + formData = new FormData(); + } + + qq.each(obj, function(key, val) { + key = arrayKeyName ? arrayKeyName + "[" + key + "]" : key; + + if (qq.isObject(val)) { + qq.obj2FormData(val, formData, key); + } + else if (qq.isFunction(val)) { + formData.append(key, val()); + } + else { + formData.append(key, val); + } + }); + + return formData; + }; + + qq.obj2Inputs = function(obj, form) { + var input; + + if (!form) { + form = document.createElement("form"); + } + + qq.obj2FormData(obj, { + append: function(key, val) { + input = document.createElement("input"); + input.setAttribute("name", key); + input.setAttribute("value", val); + form.appendChild(input); + } + }); + + return form; + }; + + qq.setCookie = function(name, value, days) { + var date = new Date(), + expires = ""; + + if (days) { + date.setTime(date.getTime()+(days*24*60*60*1000)); + expires = "; expires="+date.toGMTString(); + } + + document.cookie = name+"="+value+expires+"; path=/"; + }; + + qq.getCookie = function(name) { + var nameEQ = name + "=", + ca = document.cookie.split(";"), + cookie; + + qq.each(ca, function(idx, part) { + /*jshint -W116 */ + var cookiePart = part; + while (cookiePart.charAt(0) == " ") { + cookiePart = cookiePart.substring(1, cookiePart.length); + } + + if (cookiePart.indexOf(nameEQ) === 0) { + cookie = cookiePart.substring(nameEQ.length, cookiePart.length); + return false; + } + }); + + return cookie; + }; + + qq.getCookieNames = function(regexp) { + var cookies = document.cookie.split(";"), + cookieNames = []; + + qq.each(cookies, function(idx, cookie) { + cookie = qq.trimStr(cookie); + + var equalsIdx = cookie.indexOf("="); + + if (cookie.match(regexp)) { + cookieNames.push(cookie.substr(0, equalsIdx)); + } + }); + + return cookieNames; + }; + + qq.deleteCookie = function(name) { + qq.setCookie(name, "", -1); + }; + + qq.areCookiesEnabled = function() { + var randNum = Math.random() * 100000, + name = "qqCookieTest:" + randNum; + qq.setCookie(name, 1); + + if (qq.getCookie(name)) { + qq.deleteCookie(name); + return true; + } + return false; + }; + + /** + * Not recommended for use outside of Fine Uploader since this falls back to an unchecked eval if JSON.parse is not + * implemented. For a more secure JSON.parse polyfill, use Douglas Crockford's json2.js. + */ + qq.parseJson = function(json) { + /*jshint evil: true*/ + if (window.JSON && qq.isFunction(JSON.parse)) { + return JSON.parse(json); + } else { + return eval("(" + json + ")"); + } + }; + + /** + * Retrieve the extension of a file, if it exists. + * + * @param filename + * @returns {string || undefined} + */ + qq.getExtension = function(filename) { + var extIdx = filename.lastIndexOf(".") + 1; + + if (extIdx > 0) { + return filename.substr(extIdx, filename.length - extIdx); + } + }; + + qq.getFilename = function(blobOrFileInput) { + /*jslint regexp: true*/ + + if (qq.isInput(blobOrFileInput)) { + // get input value and remove path to normalize + return blobOrFileInput.value.replace(/.*(\/|\\)/, ""); + } + else if (qq.isFile(blobOrFileInput)) { + if (blobOrFileInput.fileName !== null && blobOrFileInput.fileName !== undefined) { + return blobOrFileInput.fileName; + } + } + + return blobOrFileInput.name; + }; + + /** + * A generic module which supports object disposing in dispose() method. + * */ + qq.DisposeSupport = function() { + var disposers = []; + + return { + /** Run all registered disposers */ + dispose: function() { + var disposer; + do { + disposer = disposers.shift(); + if (disposer) { + disposer(); + } + } + while (disposer); + }, + + /** Attach event handler and register de-attacher as a disposer */ + attach: function() { + var args = arguments; + /*jslint undef:true*/ + this.addDisposer(qq(args[0]).attach.apply(this, Array.prototype.slice.call(arguments, 1))); + }, + + /** Add disposer to the collection */ + addDisposer: function(disposeFunction) { + disposers.push(disposeFunction); + } + }; + }; +}()); + +/* globals qq */ +/** + * Fine Uploader top-level Error container. Inherits from `Error`. + */ +(function() { + "use strict"; + + qq.Error = function(message) { + this.message = "[Fine Uploader " + qq.version + "] " + message; + }; + + qq.Error.prototype = new Error(); +}()); + +/*global qq */ +qq.version="4.3.1"; + +/* globals qq */ +qq.supportedFeatures = (function () { + "use strict"; + + var supportsUploading, + supportsAjaxFileUploading, + supportsFolderDrop, + supportsChunking, + supportsResume, + supportsUploadViaPaste, + supportsUploadCors, + supportsDeleteFileXdr, + supportsDeleteFileCorsXhr, + supportsDeleteFileCors, + supportsFolderSelection, + supportsImagePreviews; + + + function testSupportsFileInputElement() { + var supported = true, + tempInput; + + try { + tempInput = document.createElement("input"); + tempInput.type = "file"; + qq(tempInput).hide(); + + if (tempInput.disabled) { + supported = false; + } + } + catch (ex) { + supported = false; + } + + return supported; + } + + //only way to test for Filesystem API support since webkit does not expose the DataTransfer interface + function isChrome21OrHigher() { + return (qq.chrome() || qq.opera()) && + navigator.userAgent.match(/Chrome\/[2][1-9]|Chrome\/[3-9][0-9]/) !== undefined; + } + + //only way to test for complete Clipboard API support at this time + function isChrome14OrHigher() { + return (qq.chrome() || qq.opera()) && + navigator.userAgent.match(/Chrome\/[1][4-9]|Chrome\/[2-9][0-9]/) !== undefined; + } + + //Ensure we can send cross-origin `XMLHttpRequest`s + function isCrossOriginXhrSupported() { + if (window.XMLHttpRequest) { + var xhr = qq.createXhrInstance(); + + //Commonly accepted test for XHR CORS support. + return xhr.withCredentials !== undefined; + } + + return false; + } + + //Test for (terrible) cross-origin ajax transport fallback for IE9 and IE8 + function isXdrSupported() { + return window.XDomainRequest !== undefined; + } + + // CORS Ajax requests are supported if it is either possible to send credentialed `XMLHttpRequest`s, + // or if `XDomainRequest` is an available alternative. + function isCrossOriginAjaxSupported() { + if (isCrossOriginXhrSupported()) { + return true; + } + + return isXdrSupported(); + } + + function isFolderSelectionSupported() { + // We know that folder selection is only supported in Chrome via this proprietary attribute for now + return document.createElement("input").webkitdirectory !== undefined; + } + + + supportsUploading = testSupportsFileInputElement(); + + supportsAjaxFileUploading = supportsUploading && qq.isXhrUploadSupported(); + + supportsFolderDrop = supportsAjaxFileUploading && isChrome21OrHigher(); + + supportsChunking = supportsAjaxFileUploading && qq.isFileChunkingSupported(); + + supportsResume = supportsAjaxFileUploading && supportsChunking && qq.areCookiesEnabled(); + + supportsUploadViaPaste = supportsAjaxFileUploading && isChrome14OrHigher(); + + supportsUploadCors = supportsUploading && (window.postMessage !== undefined || supportsAjaxFileUploading); + + supportsDeleteFileCorsXhr = isCrossOriginXhrSupported(); + + supportsDeleteFileXdr = isXdrSupported(); + + supportsDeleteFileCors = isCrossOriginAjaxSupported(); + + supportsFolderSelection = isFolderSelectionSupported(); + + supportsImagePreviews = supportsAjaxFileUploading && window.FileReader !== undefined; + + + return { + uploading: supportsUploading, + ajaxUploading: supportsAjaxFileUploading, + fileDrop: supportsAjaxFileUploading, //NOTE: will also return true for touch-only devices. It's not currently possible to accurately test for touch-only devices + folderDrop: supportsFolderDrop, + chunking: supportsChunking, + resume: supportsResume, + uploadCustomHeaders: supportsAjaxFileUploading, + uploadNonMultipart: supportsAjaxFileUploading, + itemSizeValidation: supportsAjaxFileUploading, + uploadViaPaste: supportsUploadViaPaste, + progressBar: supportsAjaxFileUploading, + uploadCors: supportsUploadCors, + deleteFileCorsXhr: supportsDeleteFileCorsXhr, + deleteFileCorsXdr: supportsDeleteFileXdr, //NOTE: will also return true in IE10, where XDR is also supported + deleteFileCors: supportsDeleteFileCors, + canDetermineSize: supportsAjaxFileUploading, + folderSelection: supportsFolderSelection, + imagePreviews: supportsImagePreviews, + imageValidation: supportsImagePreviews, + pause: supportsChunking + }; + +}()); + +/*globals qq*/ +qq.Promise = function() { + "use strict"; + + var successArgs, failureArgs, + successCallbacks = [], + failureCallbacks = [], + doneCallbacks = [], + state = 0; + + qq.extend(this, { + then: function(onSuccess, onFailure) { + if (state === 0) { + if (onSuccess) { + successCallbacks.push(onSuccess); + } + if (onFailure) { + failureCallbacks.push(onFailure); + } + } + else if (state === -1) { + onFailure && onFailure.apply(null, failureArgs); + } + else if (onSuccess) { + onSuccess.apply(null,successArgs); + } + + return this; + }, + + done: function(callback) { + if (state === 0) { + doneCallbacks.push(callback); + } + else { + callback.apply(null, failureArgs === undefined ? successArgs : failureArgs); + } + + return this; + }, + + success: function() { + state = 1; + successArgs = arguments; + + if (successCallbacks.length) { + qq.each(successCallbacks, function(idx, callback) { + callback.apply(null, successArgs); + }); + } + + if(doneCallbacks.length) { + qq.each(doneCallbacks, function(idx, callback) { + callback.apply(null, successArgs); + }); + } + + return this; + }, + + failure: function() { + state = -1; + failureArgs = arguments; + + if (failureCallbacks.length) { + qq.each(failureCallbacks, function(idx, callback) { + callback.apply(null, failureArgs); + }); + } + + if(doneCallbacks.length) { + qq.each(doneCallbacks, function(idx, callback) { + callback.apply(null, failureArgs); + }); + } + + return this; + } + }); +}; + +/*globals qq*/ + +/** + * This module represents an upload or "Select File(s)" button. It's job is to embed an opaque `` + * element as a child of a provided "container" element. This "container" element (`options.element`) is used to provide + * a custom style for the `` element. The ability to change the style of the container element is also + * provided here by adding CSS classes to the container on hover/focus. + * + * TODO Eliminate the mouseover and mouseout event handlers since the :hover CSS pseudo-class should now be + * available on all supported browsers. + * + * @param o Options to override the default values + */ +qq.UploadButton = function(o) { + "use strict"; + + + var disposeSupport = new qq.DisposeSupport(), + + options = { + // "Container" element + element: null, + + // If true adds `multiple` attribute to `` + multiple: false, + + // Corresponds to the `accept` attribute on the associated `` + acceptFiles: null, + + // A true value allows folders to be selected, if supported by the UA + folders: false, + + // `name` attribute of `` + name: "qqfile", + + // Called when the browser invokes the onchange handler on the `` + onChange: function(input) {}, + + // **This option will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers + hoverClass: "qq-upload-button-hover", + + focusClass: "qq-upload-button-focus" + }, + input, buttonId; + + // Overrides any of the default option values with any option values passed in during construction. + qq.extend(options, o); + + buttonId = qq.getUniqueId(); + + // Embed an opaque `` element as a child of `options.element`. + function createInput() { + var input = document.createElement("input"); + + input.setAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME, buttonId); + + if (options.multiple) { + input.setAttribute("multiple", ""); + } + + if (options.folders && qq.supportedFeatures.folderSelection) { + // selecting directories is only possible in Chrome now, via a vendor-specific prefixed attribute + input.setAttribute("webkitdirectory", ""); + } + + if (options.acceptFiles) { + input.setAttribute("accept", options.acceptFiles); + } + + input.setAttribute("type", "file"); + input.setAttribute("name", options.name); + + qq(input).css({ + position: "absolute", + // in Opera only 'browse' button + // is clickable and it is located at + // the right side of the input + right: 0, + top: 0, + fontFamily: "Arial", + // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118 + fontSize: "118px", + margin: 0, + padding: 0, + cursor: "pointer", + opacity: 0 + }); + + options.element.appendChild(input); + + disposeSupport.attach(input, "change", function(){ + options.onChange(input); + }); + + // **These event handlers will be removed** in the future as the :hover CSS pseudo-class is available on all supported browsers + disposeSupport.attach(input, "mouseover", function(){ + qq(options.element).addClass(options.hoverClass); + }); + disposeSupport.attach(input, "mouseout", function(){ + qq(options.element).removeClass(options.hoverClass); + }); + + disposeSupport.attach(input, "focus", function(){ + qq(options.element).addClass(options.focusClass); + }); + disposeSupport.attach(input, "blur", function(){ + qq(options.element).removeClass(options.focusClass); + }); + + // IE and Opera, unfortunately have 2 tab stops on file input + // which is unacceptable in our case, disable keyboard access + if (window.attachEvent) { + // it is IE or Opera + input.setAttribute("tabIndex", "-1"); + } + + return input; + } + + // Make button suitable container for input + qq(options.element).css({ + position: "relative", + overflow: "hidden", + // Make sure browse button is in the right side in Internet Explorer + direction: "ltr" + }); + + input = createInput(); + + + // Exposed API + qq.extend(this, { + getInput: function() { + return input; + }, + + getButtonId: function() { + return buttonId; + }, + + setMultiple: function(isMultiple) { + if (isMultiple !== options.multiple) { + if (isMultiple) { + input.setAttribute("multiple", ""); + } + else { + input.removeAttribute("multiple"); + } + } + }, + + setAcceptFiles: function(acceptFiles) { + if (acceptFiles !== options.acceptFiles) { + input.setAttribute("accept", acceptFiles); + } + }, + + reset: function(){ + if (input.parentNode){ + qq(input).remove(); + } + + qq(options.element).removeClass(options.focusClass); + input = createInput(); + } + }); +}; + +qq.UploadButton.BUTTON_ID_ATTR_NAME = "qq-button-id"; + +/*globals qq */ +qq.UploadData = function(uploaderProxy) { + "use strict"; + + var data = [], + byUuid = {}, + byStatus = {}; + + + function getDataByIds(idOrIds) { + if (qq.isArray(idOrIds)) { + var entries = []; + + qq.each(idOrIds, function(idx, id) { + entries.push(data[id]); + }); + + return entries; + } + + return data[idOrIds]; + } + + function getDataByUuids(uuids) { + if (qq.isArray(uuids)) { + var entries = []; + + qq.each(uuids, function(idx, uuid) { + entries.push(data[byUuid[uuid]]); + }); + + return entries; + } + + return data[byUuid[uuids]]; + } + + function getDataByStatus(status) { + var statusResults = [], + statuses = [].concat(status); + + qq.each(statuses, function(index, statusEnum) { + var statusResultIndexes = byStatus[statusEnum]; + + if (statusResultIndexes !== undefined) { + qq.each(statusResultIndexes, function(i, dataIndex) { + statusResults.push(data[dataIndex]); + }); + } + }); + + return statusResults; + } + + qq.extend(this, { + /** + * Adds a new file to the data cache for tracking purposes. + * + * @param uuid Initial UUID for this file. + * @param name Initial name of this file. + * @param size Size of this file, -1 if this cannot be determined + * @param status Initial `qq.status` for this file. If null/undefined, `qq.status.SUBMITTING`. + * @returns {number} Internal ID for this file. + */ + addFile: function(uuid, name, size, status) { + status = status || qq.status.SUBMITTING; + + var id = data.push({ + name: name, + originalName: name, + uuid: uuid, + size: size, + status: status + }) - 1; + + data[id].id = id; + byUuid[uuid] = id; + + if (byStatus[status] === undefined) { + byStatus[status] = []; + } + byStatus[status].push(id); + + uploaderProxy.onStatusChange(id, null, status); + + return id; + }, + + retrieve: function(optionalFilter) { + if (qq.isObject(optionalFilter) && data.length) { + if (optionalFilter.id !== undefined) { + return getDataByIds(optionalFilter.id); + } + + else if (optionalFilter.uuid !== undefined) { + return getDataByUuids(optionalFilter.uuid); + } + + else if (optionalFilter.status) { + return getDataByStatus(optionalFilter.status); + } + } + else { + return qq.extend([], data, true); + } + }, + + reset: function() { + data = []; + byUuid = {}; + byStatus = {}; + }, + + setStatus: function(id, newStatus) { + var oldStatus = data[id].status, + byStatusOldStatusIndex = qq.indexOf(byStatus[oldStatus], id); + + byStatus[oldStatus].splice(byStatusOldStatusIndex, 1); + + data[id].status = newStatus; + + if (byStatus[newStatus] === undefined) { + byStatus[newStatus] = []; + } + byStatus[newStatus].push(id); + + uploaderProxy.onStatusChange(id, oldStatus, newStatus); + }, + + uuidChanged: function(id, newUuid) { + var oldUuid = data[id].uuid; + + data[id].uuid = newUuid; + byUuid[newUuid] = id; + delete byUuid[oldUuid]; + }, + + updateName: function(id, newName) { + data[id].name = newName; + } + }); +}; + +qq.status = { + SUBMITTING: "submitting", + SUBMITTED: "submitted", + REJECTED: "rejected", + QUEUED: "queued", + CANCELED: "canceled", + PAUSED: "paused", + UPLOADING: "uploading", + UPLOAD_RETRYING: "retrying upload", + UPLOAD_SUCCESSFUL: "upload successful", + UPLOAD_FAILED: "upload failed", + DELETE_FAILED: "delete failed", + DELETING: "deleting", + DELETED: "deleted" +}; + +/*globals qq*/ +/** + * Defines the public API for FineUploaderBasic mode. + */ +(function(){ + "use strict"; + + qq.basePublicApi = { + log: function(str, level) { + if (this._options.debug && (!level || level === "info")) { + qq.log("[Fine Uploader " + qq.version + "] " + str); + } + else if (level && level !== "info") { + qq.log("[Fine Uploader " + qq.version + "] " + str, level); + + } + }, + + setParams: function(params, id) { + this._paramsStore.set(params, id); + }, + + setDeleteFileParams: function(params, id) { + this._deleteFileParamsStore.set(params, id); + }, + + // Re-sets the default endpoint, an endpoint for a specific file, or an endpoint for a specific button + setEndpoint: function(endpoint, id) { + this._endpointStore.set(endpoint, id); + }, + + getInProgress: function() { + return this._uploadData.retrieve({ + status: [ + qq.status.UPLOADING, + qq.status.UPLOAD_RETRYING, + qq.status.QUEUED + ] + }).length; + }, + + getNetUploads: function() { + return this._netUploaded; + }, + + uploadStoredFiles: function() { + var idToUpload; + + if (this._storedIds.length === 0) { + this._itemError("noFilesError"); + } + else { + while (this._storedIds.length) { + idToUpload = this._storedIds.shift(); + this._uploadFile(idToUpload); + } + } + }, + + clearStoredFiles: function(){ + this._storedIds = []; + }, + + retry: function(id) { + return this._manualRetry(id); + }, + + cancel: function(id) { + this._handler.cancel(id); + }, + + cancelAll: function() { + var storedIdsCopy = [], + self = this; + + qq.extend(storedIdsCopy, this._storedIds); + qq.each(storedIdsCopy, function(idx, storedFileId) { + self.cancel(storedFileId); + }); + + this._handler.cancelAll(); + }, + + reset: function() { + this.log("Resetting uploader..."); + + this._handler.reset(); + this._storedIds = []; + this._autoRetries = []; + this._retryTimeouts = []; + this._preventRetries = []; + this._thumbnailUrls = []; + + qq.each(this._buttons, function(idx, button) { + button.reset(); + }); + + this._paramsStore.reset(); + this._endpointStore.reset(); + this._netUploadedOrQueued = 0; + this._netUploaded = 0; + this._uploadData.reset(); + this._buttonIdsForFileIds = []; + + this._pasteHandler && this._pasteHandler.reset(); + this._options.session.refreshOnReset && this._refreshSessionData(); + + this._succeededSinceLastAllComplete = []; + this._failedSinceLastAllComplete = []; + }, + + addFiles: function(filesOrInputs, params, endpoint) { + var verifiedFilesOrInputs = [], + fileOrInputIndex, fileOrInput, fileIndex; + + if (filesOrInputs) { + if (!qq.isFileList(filesOrInputs)) { + filesOrInputs = [].concat(filesOrInputs); + } + + for (fileOrInputIndex = 0; fileOrInputIndex < filesOrInputs.length; fileOrInputIndex+=1) { + fileOrInput = filesOrInputs[fileOrInputIndex]; + + if (qq.isFileOrInput(fileOrInput)) { + if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) { + for (fileIndex = 0; fileIndex < fileOrInput.files.length; fileIndex++) { + this._handleNewFile(fileOrInput.files[fileIndex], verifiedFilesOrInputs); + } + } + else { + this._handleNewFile(fileOrInput, verifiedFilesOrInputs); + } + } + else { + this.log(fileOrInput + " is not a File or INPUT element! Ignoring!", "warn"); + } + } + + this.log("Received " + verifiedFilesOrInputs.length + " files or inputs."); + this._prepareItemsForUpload(verifiedFilesOrInputs, params, endpoint); + } + }, + + addBlobs: function(blobDataOrArray, params, endpoint) { + if (blobDataOrArray) { + var blobDataArray = [].concat(blobDataOrArray), + verifiedBlobDataList = [], + self = this; + + qq.each(blobDataArray, function(idx, blobData) { + var blobOrBlobData; + + if (qq.isBlob(blobData) && !qq.isFileOrInput(blobData)) { + blobOrBlobData = { + blob: blobData, + name: self._options.blobs.defaultName + }; + } + else if (qq.isObject(blobData) && blobData.blob && blobData.name) { + blobOrBlobData = blobData; + } + else { + self.log("addBlobs: entry at index " + idx + " is not a Blob or a BlobData object", "error"); + } + + blobOrBlobData && self._handleNewFile(blobOrBlobData, verifiedBlobDataList); + }); + + this._prepareItemsForUpload(verifiedBlobDataList, params, endpoint); + } + else { + this.log("undefined or non-array parameter passed into addBlobs", "error"); + } + }, + + getUuid: function(id) { + return this._uploadData.retrieve({id: id}).uuid; + }, + + setUuid: function(id, newUuid) { + return this._uploadData.uuidChanged(id, newUuid); + }, + + getResumableFilesData: function() { + return this._handler.getResumableFilesData(); + }, + + getSize: function(id) { + return this._uploadData.retrieve({id: id}).size; + }, + + getName: function(id) { + return this._uploadData.retrieve({id: id}).name; + }, + + setName: function(id, newName) { + this._uploadData.updateName(id, newName); + }, + + getFile: function(fileOrBlobId) { + return this._handler.getFile(fileOrBlobId); + }, + + deleteFile: function(id) { + return this._onSubmitDelete(id); + }, + + setDeleteFileEndpoint: function(endpoint, id) { + this._deleteFileEndpointStore.set(endpoint, id); + }, + + doesExist: function(fileOrBlobId) { + return this._handler.isValid(fileOrBlobId); + }, + + getUploads: function(optionalFilter) { + return this._uploadData.retrieve(optionalFilter); + }, + + getButton: function(fileId) { + return this._getButton(this._buttonIdsForFileIds[fileId]); + }, + + // Generate a variable size thumbnail on an img or canvas, + // returning a promise that is fulfilled when the attempt completes. + // Thumbnail can either be based off of a URL for an image returned + // by the server in the upload response, or the associated `Blob`. + drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer) { + if (this._imageGenerator) { + var fileOrUrl = this._thumbnailUrls[fileId], + options = { + scale: maxSize > 0, + maxSize: maxSize > 0 ? maxSize : null + }; + + // If client-side preview generation is possible + // and we are not specifically looking for the image URl returned by the server... + if (!fromServer && qq.supportedFeatures.imagePreviews) { + fileOrUrl = this.getFile(fileId); + } + + /* jshint eqeqeq:false,eqnull:true */ + if (fileOrUrl == null) { + return new qq.Promise().failure(imgOrCanvas, "File or URL not found."); + } + + return this._imageGenerator.generate(fileOrUrl, imgOrCanvas, options); + } + }, + + pauseUpload: function(id) { + var uploadData = this._uploadData.retrieve({id: id}); + + if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) { + return false; + } + + // Pause only really makes sense if the file is uploading or retrying + if (qq.indexOf([qq.status.UPLOADING, qq.status.UPLOAD_RETRYING], uploadData.status) >= 0) { + if (this._handler.pause(id)) { + this._uploadData.setStatus(id, qq.status.PAUSED); + return true; + } + else { + qq.log(qq.format("Unable to pause file ID {} ({}).", id, this.getName(id)), "error"); + } + } + else { + qq.log(qq.format("Ignoring pause for file ID {} ({}). Not in progress.", id, this.getName(id)), "error"); + } + + return false; + }, + + continueUpload: function(id) { + var uploadData = this._uploadData.retrieve({id: id}); + + if (!qq.supportedFeatures.pause || !this._options.chunking.enabled) { + return false; + } + + if (uploadData.status === qq.status.PAUSED) { + qq.log(qq.format("Paused file ID {} ({}) will be continued. Not paused.", id, this.getName(id))); + this._uploadFile(id); + return true; + } + else { + qq.log(qq.format("Ignoring continue for file ID {} ({}). Not paused.", id, this.getName(id)), "error"); + } + + return false; + }, + + getRemainingAllowedItems: function() { + var allowedItems = this._options.validation.itemLimit; + + if (allowedItems > 0) { + return this._options.validation.itemLimit - this._netUploadedOrQueued; + } + + return null; + } + }; + + + + + /** + * Defines the private (internal) API for FineUploaderBasic mode. + */ + qq.basePrivateApi = { + _initFormSupportAndParams: function() { + this._formSupport = qq.FormSupport && new qq.FormSupport( + this._options.form, qq.bind(this.uploadStoredFiles, this), qq.bind(this.log, this) + ); + + if (this._formSupport && this._formSupport.attachedToForm) { + this._paramsStore = this._createStore( + this._options.request.params, this._formSupport.getFormInputsAsObject + ); + + this._options.autoUpload = this._formSupport.newAutoUpload; + if (this._formSupport.newEndpoint) { + this._options.request.endpoint = this._formSupport.newEndpoint; + } + } + else { + this._paramsStore = this._createStore(this._options.request.params); + } + }, + + _uploadFile: function(id) { + if (!this._handler.upload(id)) { + this._uploadData.setStatus(id, qq.status.QUEUED); + } + }, + + // Attempts to refresh session data only if the `qq.Session` module exists + // and a session endpoint has been specified. The `onSessionRequestComplete` + // callback will be invoked once the refresh is complete. + _refreshSessionData: function() { + var self = this, + options = this._options.session; + + /* jshint eqnull:true */ + if (qq.Session && this._options.session.endpoint != null) { + if (!this._session) { + qq.extend(options, this._options.cors); + + options.log = qq.bind(this.log, this); + options.addFileRecord = qq.bind(this._addCannedFile, this); + + this._session = new qq.Session(options); + } + + setTimeout(function() { + self._session.refresh().then(function(response, xhrOrXdr) { + + self._options.callbacks.onSessionRequestComplete(response, true, xhrOrXdr); + + }, function(response, xhrOrXdr) { + + self._options.callbacks.onSessionRequestComplete(response, false, xhrOrXdr); + }); + }, 0); + } + }, + + // Updates internal state with a file record (not backed by a live file). Returns the assigned ID. + _addCannedFile: function(sessionData) { + var id = this._uploadData.addFile(sessionData.uuid, sessionData.name, sessionData.size, + qq.status.UPLOAD_SUCCESSFUL); + + sessionData.deleteFileEndpoint && this.setDeleteFileEndpoint(sessionData.deleteFileEndpoint, id); + sessionData.deleteFileParams && this.setDeleteFileParams(sessionData.deleteFileParams, id); + + if (sessionData.thumbnailUrl) { + this._thumbnailUrls[id] = sessionData.thumbnailUrl; + } + + this._netUploaded++; + this._netUploadedOrQueued++; + + return id; + }, + + // Updates internal state when a new file has been received, and adds it along with its ID to a passed array. + _handleNewFile: function(file, newFileWrapperList) { + var size = -1, + uuid = qq.getUniqueId(), + name = qq.getFilename(file), + id; + + if (file.size >= 0) { + size = file.size; + } + else if (file.blob) { + size = file.blob.size; + } + + id = this._uploadData.addFile(uuid, name, size); + this._handler.add(id, file); + this._trackButton(id); + + this._netUploadedOrQueued++; + + newFileWrapperList.push({id: id, file: file}); + }, + + // Maps a file with the button that was used to select it. + _trackButton: function(id) { + var buttonId; + + if (qq.supportedFeatures.ajaxUploading) { + buttonId = this._handler.getFile(id).qqButtonId; + } + else { + buttonId = this._getButtonId(this._handler.getInput(id)); + } + + if (buttonId) { + this._buttonIdsForFileIds[id] = buttonId; + } + }, + + // Creates an internal object that tracks various properties of each extra button, + // and then actually creates the extra button. + _generateExtraButtonSpecs: function() { + var self = this; + + this._extraButtonSpecs = {}; + + qq.each(this._options.extraButtons, function(idx, extraButtonOptionEntry) { + var multiple = extraButtonOptionEntry.multiple, + validation = qq.extend({}, self._options.validation, true), + extraButtonSpec = qq.extend({}, extraButtonOptionEntry); + + if (multiple === undefined) { + multiple = self._options.multiple; + } + + if (extraButtonSpec.validation) { + qq.extend(validation, extraButtonOptionEntry.validation, true); + } + + qq.extend(extraButtonSpec, { + multiple: multiple, + validation: validation + }, true); + + self._initExtraButton(extraButtonSpec); + }); + }, + + // Creates an extra button element + _initExtraButton: function(spec) { + var button = this._createUploadButton({ + element: spec.element, + multiple: spec.multiple, + accept: spec.validation.acceptFiles, + folders: spec.folders, + allowedExtensions: spec.validation.allowedExtensions + }); + + this._extraButtonSpecs[button.getButtonId()] = spec; + }, + + /** + * Gets the internally used tracking ID for a button. + * + * @param buttonOrFileInputOrFile `File`, ``, or a button container element + * @returns {*} The button's ID, or undefined if no ID is recoverable + * @private + */ + _getButtonId: function(buttonOrFileInputOrFile) { + var inputs, fileInput; + + // If the item is a `Blob` it will never be associated with a button or drop zone. + if (buttonOrFileInputOrFile && !buttonOrFileInputOrFile.blob && !qq.isBlob(buttonOrFileInputOrFile)) { + if (qq.isFile(buttonOrFileInputOrFile)) { + return buttonOrFileInputOrFile.qqButtonId; + } + else if (buttonOrFileInputOrFile.tagName.toLowerCase() === "input" && + buttonOrFileInputOrFile.type.toLowerCase() === "file") { + + return buttonOrFileInputOrFile.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME); + } + + inputs = buttonOrFileInputOrFile.getElementsByTagName("input"); + + qq.each(inputs, function(idx, input) { + if (input.getAttribute("type") === "file") { + fileInput = input; + return false; + } + }); + + if (fileInput) { + return fileInput.getAttribute(qq.UploadButton.BUTTON_ID_ATTR_NAME); + } + } + }, + + _annotateWithButtonId: function(file, associatedInput) { + if (qq.isFile(file)) { + file.qqButtonId = this._getButtonId(associatedInput); + } + }, + + _getButton: function(buttonId) { + var extraButtonsSpec = this._extraButtonSpecs[buttonId]; + + if (extraButtonsSpec) { + return extraButtonsSpec.element; + } + else if (buttonId === this._defaultButtonId) { + return this._options.button; + } + }, + + _handleCheckedCallback: function(details) { + var self = this, + callbackRetVal = details.callback(); + + if (callbackRetVal instanceof qq.Promise) { + this.log(details.name + " - waiting for " + details.name + " promise to be fulfilled for " + details.identifier); + return callbackRetVal.then( + function(successParam) { + self.log(details.name + " promise success for " + details.identifier); + details.onSuccess(successParam); + }, + function() { + if (details.onFailure) { + self.log(details.name + " promise failure for " + details.identifier); + details.onFailure(); + } + else { + self.log(details.name + " promise failure for " + details.identifier); + } + }); + } + + if (callbackRetVal !== false) { + details.onSuccess(callbackRetVal); + } + else { + if (details.onFailure) { + this.log(details.name + " - return value was 'false' for " + details.identifier + ". Invoking failure callback."); + details.onFailure(); + } + else { + this.log(details.name + " - return value was 'false' for " + details.identifier + ". Will not proceed."); + } + } + + return callbackRetVal; + }, + + /** + * Generate a tracked upload button. + * + * @param spec Object containing a required `element` property + * along with optional `multiple`, `accept`, and `folders`. + * @returns {qq.UploadButton} + * @private + */ + _createUploadButton: function(spec) { + var self = this, + acceptFiles = spec.accept || this._options.validation.acceptFiles, + allowedExtensions = spec.allowedExtensions || this._options.validation.allowedExtensions; + + function allowMultiple() { + if (qq.supportedFeatures.ajaxUploading) { + // Workaround for bug in iOS7 (see #1039) + if (qq.ios7() && self._isAllowedExtension(allowedExtensions, ".mov")) { + return false; + } + + if (spec.multiple === undefined) { + return self._options.multiple; + } + + return spec.multiple; + } + + return false; + } + + var button = new qq.UploadButton({ + element: spec.element, + folders: spec.folders, + name: this._options.request.inputName, + multiple: allowMultiple(), + acceptFiles: acceptFiles, + onChange: function(input) { + self._onInputChange(input); + }, + hoverClass: this._options.classes.buttonHover, + focusClass: this._options.classes.buttonFocus + }); + + this._disposeSupport.addDisposer(function() { + button.dispose(); + }); + + self._buttons.push(button); + + return button; + }, + + _createUploadHandler: function(additionalOptions, namespace) { + var self = this, + options = { + debug: this._options.debug, + maxConnections: this._options.maxConnections, + cors: this._options.cors, + demoMode: this._options.demoMode, + paramsStore: this._paramsStore, + endpointStore: this._endpointStore, + chunking: this._options.chunking, + resume: this._options.resume, + blobs: this._options.blobs, + log: qq.bind(self.log, self), + onProgress: function(id, name, loaded, total){ + self._onProgress(id, name, loaded, total); + self._options.callbacks.onProgress(id, name, loaded, total); + }, + onComplete: function(id, name, result, xhr){ + var retVal = self._onComplete(id, name, result, xhr); + + // If the internal `_onComplete` handler returns a promise, don't invoke the `onComplete` callback + // until the promise has been fulfilled. + if (retVal instanceof qq.Promise) { + retVal.done(function() { + self._options.callbacks.onComplete(id, name, result, xhr); + }); + } + else { + self._options.callbacks.onComplete(id, name, result, xhr); + } + }, + onCancel: function(id, name) { + return self._handleCheckedCallback({ + name: "onCancel", + callback: qq.bind(self._options.callbacks.onCancel, self, id, name), + onSuccess: qq.bind(self._onCancel, self, id, name), + identifier: id + }); + }, + onUpload: function(id, name) { + self._onUpload(id, name); + self._options.callbacks.onUpload(id, name); + }, + onUploadChunk: function(id, name, chunkData) { + self._onUploadChunk(id, chunkData); + self._options.callbacks.onUploadChunk(id, name, chunkData); + }, + onUploadChunkSuccess: function(id, chunkData, result, xhr) { + self._options.callbacks.onUploadChunkSuccess.apply(self, arguments); + }, + onResume: function(id, name, chunkData) { + return self._options.callbacks.onResume(id, name, chunkData); + }, + onAutoRetry: function(id, name, responseJSON, xhr) { + return self._onAutoRetry.apply(self, arguments); + }, + onUuidChanged: function(id, newUuid) { + self.log("Server requested UUID change from '" + self.getUuid(id) + "' to '" + newUuid + "'"); + self.setUuid(id, newUuid); + }, + getName: qq.bind(self.getName, self), + getUuid: qq.bind(self.getUuid, self), + getSize: qq.bind(self.getSize, self) + }; + + qq.each(this._options.request, function(prop, val) { + options[prop] = val; + }); + + if (additionalOptions) { + qq.each(additionalOptions, function(key, val) { + options[key] = val; + }); + } + + return new qq.UploadHandler(options, namespace); + }, + + _createDeleteHandler: function() { + var self = this; + + return new qq.DeleteFileAjaxRequester({ + method: this._options.deleteFile.method.toUpperCase(), + maxConnections: this._options.maxConnections, + uuidParamName: this._options.request.uuidName, + customHeaders: this._options.deleteFile.customHeaders, + paramsStore: this._deleteFileParamsStore, + endpointStore: this._deleteFileEndpointStore, + demoMode: this._options.demoMode, + cors: this._options.cors, + log: qq.bind(self.log, self), + onDelete: function(id) { + self._onDelete(id); + self._options.callbacks.onDelete(id); + }, + onDeleteComplete: function(id, xhrOrXdr, isError) { + self._onDeleteComplete(id, xhrOrXdr, isError); + self._options.callbacks.onDeleteComplete(id, xhrOrXdr, isError); + } + + }); + }, + + _createPasteHandler: function() { + var self = this; + + return new qq.PasteSupport({ + targetElement: this._options.paste.targetElement, + callbacks: { + log: qq.bind(self.log, self), + pasteReceived: function(blob) { + self._handleCheckedCallback({ + name: "onPasteReceived", + callback: qq.bind(self._options.callbacks.onPasteReceived, self, blob), + onSuccess: qq.bind(self._handlePasteSuccess, self, blob), + identifier: "pasted image" + }); + } + } + }); + }, + + _createUploadDataTracker: function() { + var self = this; + + return new qq.UploadData({ + getName: function(id) { + return self.getName(id); + }, + getUuid: function(id) { + return self.getUuid(id); + }, + getSize: function(id) { + return self.getSize(id); + }, + onStatusChange: function(id, oldStatus, newStatus) { + self._onUploadStatusChange(id, oldStatus, newStatus); + self._options.callbacks.onStatusChange(id, oldStatus, newStatus); + self._maybeAllComplete(id, newStatus); + } + }); + }, + + _onUploadStatusChange: function(id, oldStatus, newStatus) { + // Make sure a "queued" retry attempt is canceled if the upload has been paused + if (newStatus === qq.status.PAUSED) { + clearTimeout(this._retryTimeouts[id]); + } + }, + + _handlePasteSuccess: function(blob, extSuppliedName) { + var extension = blob.type.split("/")[1], + name = extSuppliedName; + + /*jshint eqeqeq: true, eqnull: true*/ + if (name == null) { + name = this._options.paste.defaultName; + } + + name += "." + extension; + + this.addBlobs({ + name: name, + blob: blob + }); + }, + + _preventLeaveInProgress: function(){ + var self = this; + + this._disposeSupport.attach(window, "beforeunload", function(e){ + if (self.getInProgress()) { + e = e || window.event; + // for ie, ff + e.returnValue = self._options.messages.onLeave; + // for webkit + return self._options.messages.onLeave; + } + }); + }, + + _onSubmit: function(id, name) { + //nothing to do yet in core uploader + }, + + _onProgress: function(id, name, loaded, total) { + //nothing to do yet in core uploader + }, + + _onComplete: function(id, name, result, xhr) { + if (!result.success) { + this._netUploadedOrQueued--; + this._uploadData.setStatus(id, qq.status.UPLOAD_FAILED); + } + else { + if (result.thumbnailUrl) { + this._thumbnailUrls[id] = result.thumbnailUrl; + } + + this._netUploaded++; + this._uploadData.setStatus(id, qq.status.UPLOAD_SUCCESSFUL); + } + + this._maybeParseAndSendUploadError(id, name, result, xhr); + + return result.success ? true : false; + }, + + _maybeAllComplete: function(id, status) { + var self = this, + notFinished = this._uploadData.retrieve({ + status: [ + qq.status.UPLOADING, + qq.status.UPLOAD_RETRYING, + qq.status.QUEUED, + qq.status.SUBMITTING, + qq.status.SUBMITTED, + qq.status.PAUSED, + ] + }).length; + + if (status === qq.status.UPLOAD_SUCCESSFUL) { + this._succeededSinceLastAllComplete.push(id); + } + else if (status === qq.status.UPLOAD_FAILED) { + this._failedSinceLastAllComplete.push(id); + } + + if (notFinished === 0 && + (this._succeededSinceLastAllComplete.length || this._failedSinceLastAllComplete.length)) { + // Attempt to ensure onAllComplete is not invoked before other callbacks, such as onCancel & onComplete + setTimeout(function() { + self._options.callbacks.onAllComplete( + qq.extend([], self._succeededSinceLastAllComplete), + qq.extend([], self._failedSinceLastAllComplete) + ); + + self._succeededSinceLastAllComplete = []; + self._failedSinceLastAllComplete = []; + }, 0); + } + }, + + _onCancel: function(id, name) { + this._netUploadedOrQueued--; + + clearTimeout(this._retryTimeouts[id]); + + var storedItemIndex = qq.indexOf(this._storedIds, id); + if (!this._options.autoUpload && storedItemIndex >= 0) { + this._storedIds.splice(storedItemIndex, 1); + } + + this._uploadData.setStatus(id, qq.status.CANCELED); + }, + + _isDeletePossible: function() { + if (!qq.DeleteFileAjaxRequester || !this._options.deleteFile.enabled) { + return false; + } + + if (this._options.cors.expected) { + if (qq.supportedFeatures.deleteFileCorsXhr) { + return true; + } + + if (qq.supportedFeatures.deleteFileCorsXdr && this._options.cors.allowXdr) { + return true; + } + + return false; + } + + return true; + }, + + _onSubmitDelete: function(id, onSuccessCallback, additionalMandatedParams) { + var uuid = this.getUuid(id), + adjustedOnSuccessCallback; + + if (onSuccessCallback) { + adjustedOnSuccessCallback = qq.bind(onSuccessCallback, this, id, uuid, additionalMandatedParams); + } + + if (this._isDeletePossible()) { + this._handleCheckedCallback({ + name: "onSubmitDelete", + callback: qq.bind(this._options.callbacks.onSubmitDelete, this, id), + onSuccess: adjustedOnSuccessCallback || + qq.bind(this._deleteHandler.sendDelete, this, id, uuid, additionalMandatedParams), + identifier: id + }); + return true; + } + else { + this.log("Delete request ignored for ID " + id + ", delete feature is disabled or request not possible " + + "due to CORS on a user agent that does not support pre-flighting.", "warn"); + return false; + } + }, + + _onDelete: function(id) { + this._uploadData.setStatus(id, qq.status.DELETING); + }, + + _onDeleteComplete: function(id, xhrOrXdr, isError) { + var name = this.getName(id); + + if (isError) { + this._uploadData.setStatus(id, qq.status.DELETE_FAILED); + this.log("Delete request for '" + name + "' has failed.", "error"); + + // For error reporing, we only have accesss to the response status if this is not + // an `XDomainRequest`. + if (xhrOrXdr.withCredentials === undefined) { + this._options.callbacks.onError(id, name, "Delete request failed", xhrOrXdr); + } + else { + this._options.callbacks.onError(id, name, "Delete request failed with response code " + xhrOrXdr.status, xhrOrXdr); + } + } + else { + this._netUploadedOrQueued--; + this._netUploaded--; + this._handler.expunge(id); + this._uploadData.setStatus(id, qq.status.DELETED); + this.log("Delete request for '" + name + "' has succeeded."); + } + }, + + _onUpload: function(id, name) { + this._uploadData.setStatus(id, qq.status.UPLOADING); + }, + + _onUploadChunk: function(id, chunkData) { + //nothing to do in the base uploader + }, + + _onInputChange: function(input) { + var fileIndex; + + if (qq.supportedFeatures.ajaxUploading) { + for (fileIndex = 0; fileIndex < input.files.length; fileIndex++) { + this._annotateWithButtonId(input.files[fileIndex], input); + } + + this.addFiles(input.files); + } + // Android 2.3.x will fire `onchange` even if no file has been selected + else if (input.value.length > 0) { + this.addFiles(input); + } + + qq.each(this._buttons, function(idx, button) { + button.reset(); + }); + }, + + _onBeforeAutoRetry: function(id, name) { + this.log("Waiting " + this._options.retry.autoAttemptDelay + " seconds before retrying " + name + "..."); + }, + + /** + * Attempt to automatically retry a failed upload. + * + * @param id The file ID of the failed upload + * @param name The name of the file associated with the failed upload + * @param responseJSON Response from the server, parsed into a javascript object + * @param xhr Ajax transport used to send the failed request + * @param callback Optional callback to be invoked if a retry is prudent. + * Invoked in lieu of asking the upload handler to retry. + * @returns {boolean} true if an auto-retry will occur + * @private + */ + _onAutoRetry: function(id, name, responseJSON, xhr, callback) { + var self = this; + + self._preventRetries[id] = responseJSON[self._options.retry.preventRetryResponseProperty]; + + if (self._shouldAutoRetry(id, name, responseJSON)) { + self._maybeParseAndSendUploadError.apply(self, arguments); + self._options.callbacks.onAutoRetry(id, name, self._autoRetries[id] + 1); + self._onBeforeAutoRetry(id, name); + + self._retryTimeouts[id] = setTimeout(function() { + self.log("Retrying " + name + "..."); + self._autoRetries[id]++; + self._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING); + + if (callback) { + callback(id); + } + else { + self._handler.retry(id); + } + }, self._options.retry.autoAttemptDelay * 1000); + + return true; + } + }, + + _shouldAutoRetry: function(id, name, responseJSON) { + var uploadData = this._uploadData.retrieve({id: id}); + + /*jshint laxbreak: true */ + if (!this._preventRetries[id] + && this._options.retry.enableAuto + && uploadData.status !== qq.status.PAUSED) { + + if (this._autoRetries[id] === undefined) { + this._autoRetries[id] = 0; + } + + return this._autoRetries[id] < this._options.retry.maxAutoAttempts; + } + + return false; + }, + + //return false if we should not attempt the requested retry + _onBeforeManualRetry: function(id) { + var itemLimit = this._options.validation.itemLimit; + + if (this._preventRetries[id]) { + this.log("Retries are forbidden for id " + id, "warn"); + return false; + } + else if (this._handler.isValid(id)) { + var fileName = this.getName(id); + + if (this._options.callbacks.onManualRetry(id, fileName) === false) { + return false; + } + + if (itemLimit > 0 && this._netUploadedOrQueued+1 > itemLimit) { + this._itemError("retryFailTooManyItems"); + return false; + } + + this.log("Retrying upload for '" + fileName + "' (id: " + id + ")..."); + return true; + } + else { + this.log("'" + id + "' is not a valid file ID", "error"); + return false; + } + }, + + /** + * Conditionally orders a manual retry of a failed upload. + * + * @param id File ID of the failed upload + * @param callback Optional callback to invoke if a retry is prudent. + * In lieu of asking the upload handler to retry. + * @returns {boolean} true if a manual retry will occur + * @private + */ + _manualRetry: function(id, callback) { + if (this._onBeforeManualRetry(id)) { + this._netUploadedOrQueued++; + this._uploadData.setStatus(id, qq.status.UPLOAD_RETRYING); + + if (callback) { + callback(id); + } + else { + this._handler.retry(id); + } + + return true; + } + }, + + _maybeParseAndSendUploadError: function(id, name, response, xhr) { + // Assuming no one will actually set the response code to something other than 200 + // and still set 'success' to true... + if (!response.success){ + if (xhr && xhr.status !== 200 && !response.error) { + this._options.callbacks.onError(id, name, "XHR returned response code " + xhr.status, xhr); + } + else { + var errorReason = response.error ? response.error : this._options.text.defaultResponseError; + this._options.callbacks.onError(id, name, errorReason, xhr); + } + } + }, + + _prepareItemsForUpload: function(items, params, endpoint) { + if (items.length === 0) { + this._itemError("noFilesError"); + return; + } + + var validationDescriptors = this._getValidationDescriptors(items), + buttonId = this._getButtonId(items[0].file), + button = this._getButton(buttonId); + + this._handleCheckedCallback({ + name: "onValidateBatch", + callback: qq.bind(this._options.callbacks.onValidateBatch, this, validationDescriptors, button), + onSuccess: qq.bind(this._onValidateBatchCallbackSuccess, this, validationDescriptors, items, params, endpoint, button), + onFailure: qq.bind(this._onValidateBatchCallbackFailure, this, items), + identifier: "batch validation" + }); + }, + + _upload: function(id, params, endpoint) { + var name = this.getName(id); + + if (params) { + this.setParams(params, id); + } + + if (endpoint) { + this.setEndpoint(endpoint, id); + } + + this._handleCheckedCallback({ + name: "onSubmit", + callback: qq.bind(this._options.callbacks.onSubmit, this, id, name), + onSuccess: qq.bind(this._onSubmitCallbackSuccess, this, id, name), + onFailure: qq.bind(this._fileOrBlobRejected, this, id, name), + identifier: id + }); + }, + + _onSubmitCallbackSuccess: function(id, name) { + this._onSubmit.apply(this, arguments); + this._uploadData.setStatus(id, qq.status.SUBMITTED); + this._onSubmitted.apply(this, arguments); + this._options.callbacks.onSubmitted.apply(this, arguments); + + if (this._options.autoUpload) { + this._uploadFile(id); + } + else { + this._storeForLater(id); + } + }, + + _onSubmitted: function(id) { + //nothing to do in the base uploader + }, + + _storeForLater: function(id) { + this._storedIds.push(id); + }, + + _onValidateBatchCallbackSuccess: function(validationDescriptors, items, params, endpoint, button) { + var errorMessage, + itemLimit = this._options.validation.itemLimit, + proposedNetFilesUploadedOrQueued = this._netUploadedOrQueued; + + if (itemLimit === 0 || proposedNetFilesUploadedOrQueued <= itemLimit) { + if (items.length > 0) { + this._handleCheckedCallback({ + name: "onValidate", + callback: qq.bind(this._options.callbacks.onValidate, this, validationDescriptors[0], button), + onSuccess: qq.bind(this._onValidateCallbackSuccess, this, items, 0, params, endpoint), + onFailure: qq.bind(this._onValidateCallbackFailure, this, items, 0, params, endpoint), + identifier: "Item '" + items[0].file.name + "', size: " + items[0].file.size + }); + } + else { + this._itemError("noFilesError"); + } + } + else { + this._onValidateBatchCallbackFailure(items); + errorMessage = this._options.messages.tooManyItemsError + .replace(/\{netItems\}/g, proposedNetFilesUploadedOrQueued) + .replace(/\{itemLimit\}/g, itemLimit); + this._batchError(errorMessage); + } + }, + + _onValidateBatchCallbackFailure: function(fileWrappers) { + var self = this; + + qq.each(fileWrappers, function(idx, fileWrapper) { + self._fileOrBlobRejected(fileWrapper.id); + }); + }, + + _onValidateCallbackSuccess: function(items, index, params, endpoint) { + var self = this, + nextIndex = index+1, + validationDescriptor = this._getValidationDescriptor(items[index].file); + + this._validateFileOrBlobData(items[index], validationDescriptor) + .then( + function() { + self._upload(items[index].id, params, endpoint); + self._maybeProcessNextItemAfterOnValidateCallback(true, items, nextIndex, params, endpoint); + }, + function() { + self._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint); + } + ); + }, + + _onValidateCallbackFailure: function(items, index, params, endpoint) { + var nextIndex = index+ 1; + + this._fileOrBlobRejected(items[0].id, items[0].file.name); + + this._maybeProcessNextItemAfterOnValidateCallback(false, items, nextIndex, params, endpoint); + }, + + _maybeProcessNextItemAfterOnValidateCallback: function(validItem, items, index, params, endpoint) { + var self = this; + + if (items.length > index) { + if (validItem || !this._options.validation.stopOnFirstInvalidFile) { + //use setTimeout to prevent a stack overflow with a large number of files in the batch & non-promissory callbacks + setTimeout(function() { + var validationDescriptor = self._getValidationDescriptor(items[index].file); + + self._handleCheckedCallback({ + name: "onValidate", + callback: qq.bind(self._options.callbacks.onValidate, self, items[index].file), + onSuccess: qq.bind(self._onValidateCallbackSuccess, self, items, index, params, endpoint), + onFailure: qq.bind(self._onValidateCallbackFailure, self, items, index, params, endpoint), + identifier: "Item '" + validationDescriptor.name + "', size: " + validationDescriptor.size + }); + }, 0); + } + else if (!validItem) { + for (; index < items.length; index++) { + self._fileOrBlobRejected(items[index].id); + } + } + } + }, + + /** + * Performs some internal validation checks on an item, defined in the `validation` option. + * + * @param fileWrapper Wrapper containing a `file` along with an `id` + * @param validationDescriptor Normalized information about the item (`size`, `name`). + * @returns qq.Promise with appropriate callbacks invoked depending on the validity of the file + * @private + */ + _validateFileOrBlobData: function(fileWrapper, validationDescriptor) { + var self = this, + file = fileWrapper.file, + name = validationDescriptor.name, + size = validationDescriptor.size, + buttonId = this._getButtonId(file), + validationBase = this._getValidationBase(buttonId), + validityChecker = new qq.Promise(); + + validityChecker.then( + function() {}, + function() { + self._fileOrBlobRejected(fileWrapper.id, name); + }); + + if (qq.isFileOrInput(file) && !this._isAllowedExtension(validationBase.allowedExtensions, name)) { + this._itemError("typeError", name, file); + return validityChecker.failure(); + } + + if (size === 0) { + this._itemError("emptyError", name, file); + return validityChecker.failure(); + } + + if (size && validationBase.sizeLimit && size > validationBase.sizeLimit) { + this._itemError("sizeError", name, file); + return validityChecker.failure(); + } + + if (size && size < validationBase.minSizeLimit) { + this._itemError("minSizeError", name, file); + return validityChecker.failure(); + } + + if (qq.ImageValidation && qq.supportedFeatures.imagePreviews && qq.isFile(file)) { + new qq.ImageValidation(file, qq.bind(self.log, self)).validate(validationBase.image).then( + validityChecker.success, + function(errorCode) { + self._itemError(errorCode + "ImageError", name, file); + validityChecker.failure(); + } + ); + } + else { + validityChecker.success(); + } + + return validityChecker; + }, + + _fileOrBlobRejected: function(id) { + this._netUploadedOrQueued--; + this._uploadData.setStatus(id, qq.status.REJECTED); + }, + + /** + * Constructs and returns a message that describes an item/file error. Also calls `onError` callback. + * + * @param code REQUIRED - a code that corresponds to a stock message describing this type of error + * @param maybeNameOrNames names of the items that have failed, if applicable + * @param item `File`, `Blob`, or `` + * @private + */ + _itemError: function(code, maybeNameOrNames, item) { + var message = this._options.messages[code], + allowedExtensions = [], + names = [].concat(maybeNameOrNames), + name = names[0], + buttonId = this._getButtonId(item), + validationBase = this._getValidationBase(buttonId), + extensionsForMessage, placeholderMatch; + + function r(name, replacement){ message = message.replace(name, replacement); } + + qq.each(validationBase.allowedExtensions, function(idx, allowedExtension) { + /** + * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the + * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details. + */ + if (qq.isString(allowedExtension)) { + allowedExtensions.push(allowedExtension); + } + }); + + extensionsForMessage = allowedExtensions.join(", ").toLowerCase(); + + r("{file}", this._options.formatFileName(name)); + r("{extensions}", extensionsForMessage); + r("{sizeLimit}", this._formatSize(validationBase.sizeLimit)); + r("{minSizeLimit}", this._formatSize(validationBase.minSizeLimit)); + + placeholderMatch = message.match(/(\{\w+\})/g); + if (placeholderMatch !== null) { + qq.each(placeholderMatch, function(idx, placeholder) { + r(placeholder, names[idx]); + }); + } + + this._options.callbacks.onError(null, name, message, undefined); + + return message; + }, + + _batchError: function(message) { + this._options.callbacks.onError(null, null, message, undefined); + }, + + _isAllowedExtension: function(allowed, fileName) { + var valid = false; + + if (!allowed.length) { + return true; + } + + qq.each(allowed, function(idx, allowedExt) { + /** + * If an argument is not a string, ignore it. Added when a possible issue with MooTools hijacking the + * `allowedExtensions` array was discovered. See case #735 in the issue tracker for more details. + */ + if (qq.isString(allowedExt)) { + /*jshint eqeqeq: true, eqnull: true*/ + var extRegex = new RegExp("\\." + allowedExt + "$", "i"); + + if (fileName.match(extRegex) != null) { + valid = true; + return false; + } + } + }); + + return valid; + }, + + _formatSize: function(bytes){ + var i = -1; + do { + bytes = bytes / 1000; + i++; + } while (bytes > 999); + + return Math.max(bytes, 0.1).toFixed(1) + this._options.text.sizeSymbols[i]; + }, + + _wrapCallbacks: function() { + var self, safeCallback; + + self = this; + + safeCallback = function(name, callback, args) { + var errorMsg; + + try { + return callback.apply(self, args); + } + catch (exception) { + errorMsg = exception.message || exception.toString(); + self.log("Caught exception in '" + name + "' callback - " + errorMsg, "error"); + } + }; + + /* jshint forin: false, loopfunc: true */ + for (var prop in this._options.callbacks) { + (function() { + var callbackName, callbackFunc; + callbackName = prop; + callbackFunc = self._options.callbacks[callbackName]; + self._options.callbacks[callbackName] = function() { + return safeCallback(callbackName, callbackFunc, arguments); + }; + }()); + } + }, + + _parseFileOrBlobDataName: function(fileOrBlobData) { + var name; + + if (qq.isFileOrInput(fileOrBlobData)) { + if (fileOrBlobData.value) { + // it is a file input + // get input value and remove path to normalize + name = fileOrBlobData.value.replace(/.*(\/|\\)/, ""); + } else { + // fix missing properties in Safari 4 and firefox 11.0a2 + name = (fileOrBlobData.fileName !== null && fileOrBlobData.fileName !== undefined) ? fileOrBlobData.fileName : fileOrBlobData.name; + } + } + else { + name = fileOrBlobData.name; + } + + return name; + }, + + _parseFileOrBlobDataSize: function(fileOrBlobData) { + var size; + + if (qq.isFileOrInput(fileOrBlobData)) { + if (fileOrBlobData.value === undefined) { + // fix missing properties in Safari 4 and firefox 11.0a2 + size = (fileOrBlobData.fileSize !== null && fileOrBlobData.fileSize !== undefined) ? fileOrBlobData.fileSize : fileOrBlobData.size; + } + } + else { + size = fileOrBlobData.blob.size; + } + + return size; + }, + + _getValidationDescriptor: function(fileOrBlobData) { + var fileDescriptor = {}, + name = this._parseFileOrBlobDataName(fileOrBlobData), + size = this._parseFileOrBlobDataSize(fileOrBlobData); + + fileDescriptor.name = name; + if (size !== undefined) { + fileDescriptor.size = size; + } + + return fileDescriptor; + }, + + _getValidationDescriptors: function(fileWrappers) { + var self = this, + fileDescriptors = []; + + qq.each(fileWrappers, function(idx, fileWrapper) { + fileDescriptors.push(self._getValidationDescriptor(fileWrapper.file)); + }); + + return fileDescriptors; + }, + + _createStore: function(initialValue, readOnlyValues) { + var store = {}, + catchall = initialValue, + copy = function(orig) { + if (qq.isObject(orig)) { + return qq.extend({}, orig); + } + return orig; + }, + getReadOnlyValues = function() { + if (qq.isFunction(readOnlyValues)) { + return readOnlyValues(); + } + return readOnlyValues; + }, + includeReadOnlyValues = function(existing) { + if (readOnlyValues && qq.isObject(existing)) { + qq.extend(existing, getReadOnlyValues()); + } + }; + + return { + set: function(val, id) { + /*jshint eqeqeq: true, eqnull: true*/ + if (id == null) { + store = {}; + catchall = copy(val); + } + else { + store[id] = copy(val); + } + }, + + get: function(id) { + var values; + + /*jshint eqeqeq: true, eqnull: true*/ + if (id != null && store[id]) { + values = store[id]; + } + else { + values = catchall; + } + + includeReadOnlyValues(values); + + return copy(values); + }, + + remove: function(fileId) { + return delete store[fileId]; + }, + + reset: function() { + store = {}; + catchall = initialValue; + } + }; + }, + + // Allows camera access on either the default or an extra button for iOS devices. + _handleCameraAccess: function() { + if (this._options.camera.ios && qq.ios()) { + var acceptIosCamera = "image/*;capture=camera", + button = this._options.camera.button, + buttonId = button ? this._getButtonId(button) : this._defaultButtonId, + optionRoot = this._options; + + // If we are not targeting the default button, it is an "extra" button + if (buttonId && buttonId !== this._defaultButtonId) { + optionRoot = this._extraButtonSpecs[buttonId]; + } + + // Camera access won't work in iOS if the `multiple` attribute is present on the file input + optionRoot.multiple = false; + + // update the options + if (optionRoot.validation.acceptFiles === null) { + optionRoot.validation.acceptFiles = acceptIosCamera; + } + else { + optionRoot.validation.acceptFiles += "," + acceptIosCamera; + } + + // update the already-created button + qq.each(this._buttons, function(idx, button) { + if (button.getButtonId() === buttonId) { + button.setMultiple(optionRoot.multiple); + button.setAcceptFiles(optionRoot.acceptFiles); + + return false; + } + }); + } + }, + + // Get the validation options for this button. Could be the default validation option + // or a specific one assigned to this particular button. + _getValidationBase: function(buttonId) { + var extraButtonSpec = this._extraButtonSpecs[buttonId]; + + return extraButtonSpec ? extraButtonSpec.validation : this._options.validation; + } + }; +}()); + +/*globals qq*/ +(function(){ + "use strict"; + + qq.FineUploaderBasic = function(o) { + // These options define FineUploaderBasic mode. + this._options = { + debug: false, + button: null, + multiple: true, + maxConnections: 3, + disableCancelForFormUploads: false, + autoUpload: true, + + request: { + endpoint: "/server/upload", + params: {}, + paramsInBody: true, + customHeaders: {}, + forceMultipart: true, + inputName: "qqfile", + uuidName: "qquuid", + totalFileSizeName: "qqtotalfilesize", + filenameParam: "qqfilename" + }, + + validation: { + allowedExtensions: [], + sizeLimit: 0, + minSizeLimit: 0, + itemLimit: 0, + stopOnFirstInvalidFile: true, + acceptFiles: null, + image: { + maxHeight: 0, + maxWidth: 0, + minHeight: 0, + minWidth: 0 + } + }, + + callbacks: { + onSubmit: function(id, name){}, + onSubmitted: function(id, name){}, + onComplete: function(id, name, responseJSON, maybeXhr){}, + onAllComplete: function(successful, failed) {}, + onCancel: function(id, name){}, + onUpload: function(id, name){}, + onUploadChunk: function(id, name, chunkData){}, + onUploadChunkSuccess: function(id, chunkData, responseJSON, xhr){}, + onResume: function(id, fileName, chunkData){}, + onProgress: function(id, name, loaded, total){}, + onError: function(id, name, reason, maybeXhrOrXdr) {}, + onAutoRetry: function(id, name, attemptNumber) {}, + onManualRetry: function(id, name) {}, + onValidateBatch: function(fileOrBlobData) {}, + onValidate: function(fileOrBlobData) {}, + onSubmitDelete: function(id) {}, + onDelete: function(id){}, + onDeleteComplete: function(id, xhrOrXdr, isError){}, + onPasteReceived: function(blob) {}, + onStatusChange: function(id, oldStatus, newStatus) {}, + onSessionRequestComplete: function(response, success, xhrOrXdr) {} + }, + + messages: { + typeError: "{file} has an invalid extension. Valid extension(s): {extensions}.", + sizeError: "{file} is too large, maximum file size is {sizeLimit}.", + minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.", + emptyError: "{file} is empty, please select files again without it.", + noFilesError: "No files to upload.", + tooManyItemsError: "Too many items ({netItems}) would be uploaded. Item limit is {itemLimit}.", + maxHeightImageError: "Image is too tall.", + maxWidthImageError: "Image is too wide.", + minHeightImageError: "Image is not tall enough.", + minWidthImageError: "Image is not wide enough.", + retryFailTooManyItems: "Retry failed - you have reached your file limit.", + onLeave: "The files are being uploaded, if you leave now the upload will be canceled." + }, + + retry: { + enableAuto: false, + maxAutoAttempts: 3, + autoAttemptDelay: 5, + preventRetryResponseProperty: "preventRetry" + }, + + classes: { + buttonHover: "qq-upload-button-hover", + buttonFocus: "qq-upload-button-focus" + }, + + chunking: { + enabled: false, + partSize: 2000000, + paramNames: { + partIndex: "qqpartindex", + partByteOffset: "qqpartbyteoffset", + chunkSize: "qqchunksize", + totalFileSize: "qqtotalfilesize", + totalParts: "qqtotalparts" + } + }, + + resume: { + enabled: false, + id: null, + cookiesExpireIn: 7, //days + paramNames: { + resuming: "qqresume" + } + }, + + formatFileName: function(fileOrBlobName) { + if (fileOrBlobName !== undefined && fileOrBlobName.length > 33) { + fileOrBlobName = fileOrBlobName.slice(0, 19) + "..." + fileOrBlobName.slice(-14); + } + return fileOrBlobName; + }, + + text: { + defaultResponseError: "Upload failure reason unknown", + sizeSymbols: ["kB", "MB", "GB", "TB", "PB", "EB"] + }, + + deleteFile : { + enabled: false, + method: "DELETE", + endpoint: "/server/upload", + customHeaders: {}, + params: {} + }, + + cors: { + expected: false, + sendCredentials: false, + allowXdr: false + }, + + blobs: { + defaultName: "misc_data" + }, + + paste: { + targetElement: null, + defaultName: "pasted_image" + }, + + camera: { + ios: false, + + // if ios is true: button is null means target the default button, otherwise target the button specified + button: null + }, + + // This refers to additional upload buttons to be handled by Fine Uploader. + // Each element is an object, containing `element` as the only required + // property. The `element` must be a container that will ultimately + // contain an invisible `` created by Fine Uploader. + // Optional properties of each object include `multiple`, `validation`, + // and `folders`. + extraButtons: [], + + // Depends on the session module. Used to query the server for an initial file list + // during initialization and optionally after a `reset`. + session: { + endpoint: null, + params: {}, + customHeaders: {}, + refreshOnReset: true + }, + + // Send parameters associated with an existing form along with the files + form: { + // Element ID, HTMLElement, or null + element: "qq-form", + + // Overrides the base `autoUpload`, unless `element` is null. + autoUpload: false, + + // true = upload files on form submission (and squelch submit event) + interceptSubmit: true + } + }; + + // Replace any default options with user defined ones + qq.extend(this._options, o, true); + + this._buttons = []; + this._extraButtonSpecs = {}; + this._buttonIdsForFileIds = []; + + this._wrapCallbacks(); + this._disposeSupport = new qq.DisposeSupport(); + + this._storedIds = []; + this._autoRetries = []; + this._retryTimeouts = []; + this._preventRetries = []; + this._thumbnailUrls = []; + + this._netUploadedOrQueued = 0; + this._netUploaded = 0; + this._uploadData = this._createUploadDataTracker(); + + this._initFormSupportAndParams(); + + this._deleteFileParamsStore = this._createStore(this._options.deleteFile.params); + + this._endpointStore = this._createStore(this._options.request.endpoint); + this._deleteFileEndpointStore = this._createStore(this._options.deleteFile.endpoint); + + this._handler = this._createUploadHandler(); + + this._deleteHandler = qq.DeleteFileAjaxRequester && this._createDeleteHandler(); + + if (this._options.button) { + this._defaultButtonId = this._createUploadButton({element: this._options.button}).getButtonId(); + } + + this._generateExtraButtonSpecs(); + + this._handleCameraAccess(); + + if (this._options.paste.targetElement) { + if (qq.PasteSupport) { + this._pasteHandler = this._createPasteHandler(); + } + else { + qq.log("Paste support module not found", "info"); + } + } + + this._preventLeaveInProgress(); + + this._imageGenerator = qq.ImageGenerator && new qq.ImageGenerator(qq.bind(this.log, this)); + this._refreshSessionData(); + + this._succeededSinceLastAllComplete = []; + this._failedSinceLastAllComplete = []; + }; + + // Define the private & public API methods. + qq.FineUploaderBasic.prototype = qq.basePublicApi; + qq.extend(qq.FineUploaderBasic.prototype, qq.basePrivateApi); +}()); + +/*globals qq, XDomainRequest*/ +/** Generic class for sending non-upload ajax requests and handling the associated responses **/ +qq.AjaxRequester = function (o) { + "use strict"; + + var log, shouldParamsBeInQueryString, + queue = [], + requestData = {}, + options = { + validMethods: ["POST"], + method: "POST", + contentType: "application/x-www-form-urlencoded", + maxConnections: 3, + customHeaders: {}, + endpointStore: {}, + paramsStore: {}, + mandatedParams: {}, + allowXRequestedWithAndCacheControl: true, + successfulResponseCodes: { + "DELETE": [200, 202, 204], + "POST": [200, 204], + "GET": [200] + }, + cors: { + expected: false, + sendCredentials: false + }, + log: function (str, level) {}, + onSend: function (id) {}, + onComplete: function (id, xhrOrXdr, isError) {}, + onProgress: null + }; + + qq.extend(options, o); + log = options.log; + + if (qq.indexOf(options.validMethods, options.method) < 0) { + throw new Error("'" + options.method + "' is not a supported method for this type of request!"); + } + + // [Simple methods](http://www.w3.org/TR/cors/#simple-method) + // are defined by the W3C in the CORS spec as a list of methods that, in part, + // make a CORS request eligible to be exempt from preflighting. + function isSimpleMethod() { + return qq.indexOf(["GET", "POST", "HEAD"], options.method) >= 0; + } + + // [Simple headers](http://www.w3.org/TR/cors/#simple-header) + // are defined by the W3C in the CORS spec as a list of headers that, in part, + // make a CORS request eligible to be exempt from preflighting. + function containsNonSimpleHeaders(headers) { + var containsNonSimple = false; + + qq.each(containsNonSimple, function(idx, header) { + if (qq.indexOf(["Accept", "Accept-Language", "Content-Language", "Content-Type"], header) < 0) { + containsNonSimple = true; + return false; + } + }); + + return containsNonSimple; + } + + function isXdr(xhr) { + //The `withCredentials` test is a commonly accepted way to determine if XHR supports CORS. + return options.cors.expected && xhr.withCredentials === undefined; + } + + // Returns either a new `XMLHttpRequest` or `XDomainRequest` instance. + function getCorsAjaxTransport() { + var xhrOrXdr; + + if (window.XMLHttpRequest || window.ActiveXObject) { + xhrOrXdr = qq.createXhrInstance(); + + if (xhrOrXdr.withCredentials === undefined) { + xhrOrXdr = new XDomainRequest(); + } + } + + return xhrOrXdr; + } + + // Returns either a new XHR/XDR instance, or an existing one for the associated `File` or `Blob`. + function getXhrOrXdr(id, dontCreateIfNotExist) { + var xhrOrXdr = requestData[id].xhr; + + if (!xhrOrXdr && !dontCreateIfNotExist) { + if (options.cors.expected) { + xhrOrXdr = getCorsAjaxTransport(); + } + else { + xhrOrXdr = qq.createXhrInstance(); + } + + requestData[id].xhr = xhrOrXdr; + } + + return xhrOrXdr; + } + + // Removes element from queue, sends next request + function dequeue(id) { + var i = qq.indexOf(queue, id), + max = options.maxConnections, + nextId; + + delete requestData[id]; + queue.splice(i, 1); + + if (queue.length >= max && i < max) { + nextId = queue[max - 1]; + sendRequest(nextId); + } + } + + function onComplete(id, xdrError) { + var xhr = getXhrOrXdr(id), + method = options.method, + isError = xdrError === true; + + dequeue(id); + + if (isError) { + log(method + " request for " + id + " has failed", "error"); + } + else if (!isXdr(xhr) && !isResponseSuccessful(xhr.status)) { + isError = true; + log(method + " request for " + id + " has failed - response code " + xhr.status, "error"); + } + + options.onComplete(id, xhr, isError); + } + + function getParams(id) { + var onDemandParams = requestData[id].additionalParams, + mandatedParams = options.mandatedParams, + params; + + if (options.paramsStore.get) { + params = options.paramsStore.get(id); + } + + if (onDemandParams) { + qq.each(onDemandParams, function (name, val) { + params = params || {}; + params[name] = val; + }); + } + + if (mandatedParams) { + qq.each(mandatedParams, function (name, val) { + params = params || {}; + params[name] = val; + }); + } + + return params; + } + + function sendRequest(id) { + var xhr = getXhrOrXdr(id), + method = options.method, + params = getParams(id), + payload = requestData[id].payload, + url; + + options.onSend(id); + + url = createUrl(id, params); + + // XDR and XHR status detection APIs differ a bit. + if (isXdr(xhr)) { + xhr.onload = getXdrLoadHandler(id); + xhr.onerror = getXdrErrorHandler(id); + } + else { + xhr.onreadystatechange = getXhrReadyStateChangeHandler(id); + } + + + registerForUploadProgress(id); + + // The last parameter is assumed to be ignored if we are actually using `XDomainRequest`. + xhr.open(method, url, true); + + // Instruct the transport to send cookies along with the CORS request, + // unless we are using `XDomainRequest`, which is not capable of this. + if (options.cors.expected && options.cors.sendCredentials && !isXdr(xhr)) { + xhr.withCredentials = true; + } + + setHeaders(id); + + log("Sending " + method + " request for " + id); + + if (payload) { + xhr.send(payload); + } + else if (shouldParamsBeInQueryString || !params) { + xhr.send(); + } + else if (params && options.contentType && options.contentType.toLowerCase().indexOf("application/x-www-form-urlencoded") >= 0) { + xhr.send(qq.obj2url(params, "")); + } + else if (params && options.contentType && options.contentType.toLowerCase().indexOf("application/json") >= 0) { + xhr.send(JSON.stringify(params)); + } + else { + xhr.send(params); + } + + return xhr; + } + + function createUrl(id, params) { + var endpoint = options.endpointStore.get(id), + addToPath = requestData[id].addToPath; + + /*jshint -W116,-W041 */ + if (addToPath != undefined) { + endpoint += "/" + addToPath; + } + + if (shouldParamsBeInQueryString && params) { + return qq.obj2url(params, endpoint); + } + else { + return endpoint; + } + } + + // Invoked by the UA to indicate a number of possible states that describe + // a live `XMLHttpRequest` transport. + function getXhrReadyStateChangeHandler(id) { + return function () { + if (getXhrOrXdr(id).readyState === 4) { + onComplete(id); + } + }; + } + + function registerForUploadProgress(id) { + var onProgress = options.onProgress; + + if (onProgress) { + getXhrOrXdr(id).upload.onprogress = function(e) { + if (e.lengthComputable) { + onProgress(id, e.loaded, e.total); + } + }; + } + } + + // This will be called by IE to indicate **success** for an associated + // `XDomainRequest` transported request. + function getXdrLoadHandler(id) { + return function () { + onComplete(id); + }; + } + + // This will be called by IE to indicate **failure** for an associated + // `XDomainRequest` transported request. + function getXdrErrorHandler(id) { + return function () { + onComplete(id, true); + }; + } + + function setHeaders(id) { + var xhr = getXhrOrXdr(id), + customHeaders = options.customHeaders, + onDemandHeaders = requestData[id].additionalHeaders || {}, + method = options.method, + allHeaders = {}; + + // If XDomainRequest is being used, we can't set headers, so just ignore this block. + if (!isXdr(xhr)) { + // Only attempt to add X-Requested-With & Cache-Control if permitted + if (options.allowXRequestedWithAndCacheControl) { + // Do not add X-Requested-With & Cache-Control if this is a cross-origin request + // OR the cross-origin request contains a non-simple method or header. + // This is done to ensure a preflight is not triggered exclusively based on the + // addition of these 2 non-simple headers. + if (!options.cors.expected || (!isSimpleMethod() || containsNonSimpleHeaders(customHeaders))) { + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + xhr.setRequestHeader("Cache-Control", "no-cache"); + } + } + + if (options.contentType && (method === "POST" || method === "PUT")) { + xhr.setRequestHeader("Content-Type", options.contentType); + } + + qq.extend(allHeaders, qq.isFunction(customHeaders) ? customHeaders(id) : customHeaders); + qq.extend(allHeaders, onDemandHeaders); + + qq.each(allHeaders, function (name, val) { + xhr.setRequestHeader(name, val); + }); + } + } + + function isResponseSuccessful(responseCode) { + return qq.indexOf(options.successfulResponseCodes[options.method], responseCode) >= 0; + } + + function prepareToSend(id, addToPath, additionalParams, additionalHeaders, payload) { + requestData[id] = { + addToPath: addToPath, + additionalParams: additionalParams, + additionalHeaders: additionalHeaders, + payload: payload + }; + + var len = queue.push(id); + + // if too many active connections, wait... + if (len <= options.maxConnections) { + return sendRequest(id); + } + } + + + shouldParamsBeInQueryString = options.method === "GET" || options.method === "DELETE"; + + qq.extend(this, { + // Start the process of sending the request. The ID refers to the file associated with the request. + initTransport: function(id) { + var path, params, headers, payload, cacheBuster; + + return { + // Optionally specify the end of the endpoint path for the request. + withPath: function(appendToPath) { + path = appendToPath; + return this; + }, + + // Optionally specify additional parameters to send along with the request. + // These will be added to the query string for GET/DELETE requests or the payload + // for POST/PUT requests. The Content-Type of the request will be used to determine + // how these parameters should be formatted as well. + withParams: function(additionalParams) { + params = additionalParams; + return this; + }, + + // Optionally specify additional headers to send along with the request. + withHeaders: function(additionalHeaders) { + headers = additionalHeaders; + return this; + }, + + // Optionally specify a payload/body for the request. + withPayload: function(thePayload) { + payload = thePayload; + return this; + }, + + // Appends a cache buster (timestamp) to the request URL as a query parameter (only if GET or DELETE) + withCacheBuster: function() { + cacheBuster = true; + return this; + }, + + // Send the constructed request. + send: function() { + if (cacheBuster && qq.indexOf(["GET", "DELETE"], options.method) >= 0) { + params.qqtimestamp = new Date().getTime(); + } + + return prepareToSend(id, path, params, headers, payload); + } + }; + }, + + canceled: function(id) { + dequeue(id); + } + }); +}; + +/*globals qq*/ +/** + * Base upload handler module. Delegates to more specific handlers. + * + * @param o Options. Passed along to the specific handler submodule as well. + * @param namespace [optional] Namespace for the specific handler. + */ +qq.UploadHandler = function(o, namespace) { + "use strict"; + + var queue = [], + options, log, handlerImpl; + + // Default options, can be overridden by the user + options = { + debug: false, + forceMultipart: true, + paramsInBody: false, + paramsStore: {}, + endpointStore: {}, + filenameParam: "qqfilename", + cors: { + expected: false, + sendCredentials: false + }, + maxConnections: 3, // maximum number of concurrent uploads + uuidName: "qquuid", + totalFileSizeName: "qqtotalfilesize", + chunking: { + enabled: false, + partSize: 2000000, //bytes + paramNames: { + partIndex: "qqpartindex", + partByteOffset: "qqpartbyteoffset", + chunkSize: "qqchunksize", + totalParts: "qqtotalparts", + filename: "qqfilename" + } + }, + resume: { + enabled: false, + id: null, + cookiesExpireIn: 7, //days + paramNames: { + resuming: "qqresume" + } + }, + log: function(str, level) {}, + onProgress: function(id, fileName, loaded, total){}, + onComplete: function(id, fileName, response, xhr){}, + onCancel: function(id, fileName){}, + onUpload: function(id, fileName){}, + onUploadChunk: function(id, fileName, chunkData){}, + onUploadChunkSuccess: function(id, chunkData, response, xhr){}, + onAutoRetry: function(id, fileName, response, xhr){}, + onResume: function(id, fileName, chunkData){}, + onUuidChanged: function(id, newUuid){}, + getName: function(id) {} + + }; + qq.extend(options, o); + + log = options.log; + + /** + * Removes element from queue, starts upload of next + */ + function dequeue(id) { + var i = qq.indexOf(queue, id), + max = options.maxConnections, + nextId; + + if (i >= 0) { + queue.splice(i, 1); + + if (queue.length >= max && i < max){ + nextId = queue[max-1]; + handlerImpl.upload(nextId); + } + } + } + + function cancelSuccess(id) { + log("Cancelling " + id); + options.paramsStore.remove(id); + dequeue(id); + } + + function determineHandlerImpl() { + var handlerType = namespace ? qq[namespace] : qq, + handlerModuleSubtype = qq.supportedFeatures.ajaxUploading ? "Xhr" : "Form"; + + handlerImpl = new handlerType["UploadHandler" + handlerModuleSubtype]( + options, + {onUploadComplete: dequeue, onUuidChanged: options.onUuidChanged, + getName: options.getName, getUuid: options.getUuid, getSize: options.getSize, log: log} + ); + } + + + qq.extend(this, { + /** + * Adds file or file input to the queue + * @returns id + **/ + add: function(id, file) { + return handlerImpl.add.apply(this, arguments); + }, + + /** + * Sends the file identified by id + */ + upload: function(id) { + var len = queue.push(id); + + // if too many active uploads, wait... + if (len <= options.maxConnections){ + handlerImpl.upload(id); + return true; + } + + return false; + }, + + retry: function(id) { + var i = qq.indexOf(queue, id); + if (i >= 0) { + return handlerImpl.upload(id, true); + } + else { + return this.upload(id); + } + }, + + /** + * Cancels file upload by id + */ + cancel: function(id) { + var cancelRetVal = handlerImpl.cancel(id); + + if (cancelRetVal instanceof qq.Promise) { + cancelRetVal.then(function() { + cancelSuccess(id); + }); + } + else if (cancelRetVal !== false) { + cancelSuccess(id); + } + }, + + /** + * Cancels all queued or in-progress uploads + */ + cancelAll: function() { + var self = this, + queueCopy = []; + + qq.extend(queueCopy, queue); + qq.each(queueCopy, function(idx, fileId) { + self.cancel(fileId); + }); + + queue = []; + }, + + getFile: function(id) { + if (handlerImpl.getFile) { + return handlerImpl.getFile(id); + } + }, + + getInput: function(id) { + if (handlerImpl.getInput) { + return handlerImpl.getInput(id); + } + }, + + reset: function() { + log("Resetting upload handler"); + this.cancelAll(); + queue = []; + handlerImpl.reset(); + }, + + expunge: function(id) { + if (this.isValid(id)) { + return handlerImpl.expunge(id); + } + }, + + /** + * Determine if the file exists. + */ + isValid: function(id) { + return handlerImpl.isValid(id); + }, + + getResumableFilesData: function() { + if (handlerImpl.getResumableFilesData) { + return handlerImpl.getResumableFilesData(); + } + return []; + }, + + /** + * This may or may not be implemented, depending on the handler. For handlers where a third-party ID is + * available (such as the "key" for Amazon S3), this will return that value. Otherwise, the return value + * will be undefined. + * + * @param id Internal file ID + * @returns {*} Some identifier used by a 3rd-party service involved in the upload process + */ + getThirdPartyFileId: function(id) { + if (handlerImpl.getThirdPartyFileId && this.isValid(id)) { + return handlerImpl.getThirdPartyFileId(id); + } + }, + + /** + * Attempts to pause the associated upload if the specific handler supports this and the file is "valid". + * @param id ID of the upload/file to pause + * @returns {boolean} true if the upload was paused + */ + pause: function(id) { + if (handlerImpl.pause && this.isValid(id) && handlerImpl.pause(id)) { + dequeue(id); + return true; + } + } + }); + + determineHandlerImpl(); +}; + +/* globals qq */ +/** + * Common APIs exposed to creators of upload via form/iframe handlers. This is reused and possibly overridden + * in some cases by specific form upload handlers. + * + * @constructor + */ +qq.AbstractUploadHandlerForm = function(spec) { + "use strict"; + + var options = spec.options, + handler = this, + proxy = spec.proxy, + formHandlerInstanceId = qq.getUniqueId(), + onloadCallbacks = {}, + detachLoadEvents = {}, + postMessageCallbackTimers = {}, + isCors = options.isCors, + fileState = {}, + inputName = options.inputName, + onCancel = proxy.onCancel, + onUuidChanged = proxy.onUuidChanged, + getName = proxy.getName, + getUuid = proxy.getUuid, + log = proxy.log, + corsMessageReceiver = new qq.WindowReceiveMessage({log: log}); + + + /** + * Remove any trace of the file from the handler. + * + * @param id ID of the associated file + */ + function expungeFile(id) { + delete detachLoadEvents[id]; + delete fileState[id]; + + // If we are dealing with CORS, we might still be waiting for a response from a loaded iframe. + // In that case, terminate the timer waiting for a message from the loaded iframe + // and stop listening for any more messages coming from this iframe. + if (isCors) { + clearTimeout(postMessageCallbackTimers[id]); + delete postMessageCallbackTimers[id]; + corsMessageReceiver.stopReceivingMessages(id); + } + + var iframe = document.getElementById(handler._getIframeName(id)); + if (iframe) { + // To cancel request set src to something else. We use src="javascript:false;" + // because it doesn't trigger ie6 prompt on https + iframe.setAttribute("src", "java" + String.fromCharCode(115) + "cript:false;"); //deal with "JSLint: javascript URL" warning, which apparently cannot be turned off + + qq(iframe).remove(); + } + } + + /** + * If we are in CORS mode, we must listen for messages (containing the server response) from the associated + * iframe, since we cannot directly parse the content of the iframe due to cross-origin restrictions. + * + * @param iframe Listen for messages on this iframe. + * @param callback Invoke this callback with the message from the iframe. + */ + function registerPostMessageCallback(iframe, callback) { + var iframeName = iframe.id, + fileId = getFileIdForIframeName(iframeName), + uuid = getUuid(fileId); + + onloadCallbacks[uuid] = callback; + + // When the iframe has loaded (after the server responds to an upload request) + // declare the attempt a failure if we don't receive a valid message shortly after the response comes in. + detachLoadEvents[fileId] = qq(iframe).attach("load", function() { + if (fileState[fileId].input) { + log("Received iframe load event for CORS upload request (iframe name " + iframeName + ")"); + + postMessageCallbackTimers[iframeName] = setTimeout(function() { + var errorMessage = "No valid message received from loaded iframe for iframe name " + iframeName; + log(errorMessage, "error"); + callback({ + error: errorMessage + }); + }, 1000); + } + }); + + // Listen for messages coming from this iframe. When a message has been received, cancel the timer + // that declares the upload a failure if a message is not received within a reasonable amount of time. + corsMessageReceiver.receiveMessage(iframeName, function(message) { + log("Received the following window message: '" + message + "'"); + var fileId = getFileIdForIframeName(iframeName), + response = handler._parseJsonResponse(fileId, message), + uuid = response.uuid, + onloadCallback; + + if (uuid && onloadCallbacks[uuid]) { + log("Handling response for iframe name " + iframeName); + clearTimeout(postMessageCallbackTimers[iframeName]); + delete postMessageCallbackTimers[iframeName]; + + handler._detachLoadEvent(iframeName); + + onloadCallback = onloadCallbacks[uuid]; + + delete onloadCallbacks[uuid]; + corsMessageReceiver.stopReceivingMessages(iframeName); + onloadCallback(response); + } + else if (!uuid) { + log("'" + message + "' does not contain a UUID - ignoring."); + } + }); + } + + /** + * Generates an iframe to be used as a target for upload-related form submits. This also adds the iframe + * to the current `document`. Note that the iframe is hidden from view. + * + * @param name Name of the iframe. + * @returns {HTMLIFrameElement} The created iframe + */ + function initIframeForUpload(name) { + var iframe = qq.toElement("':"application/x-shockwave-flash"==a.source1mime?(o+='',a.poster&&(o+=''),o+=""):-1!=a.source1mime.indexOf("audio")?e.settings.audio_template_callback?o=e.settings.audio_template_callback(a):o+='":"script"==a.type?o+='':o=e.settings.video_template_callback?e.settings.video_template_callback(a):'"}return o}function n(e){var t={};return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!0,special:"script,noscript",start:function(e,i){if(t.source1||"param"!=e||(t.source1=i.map.movie),("iframe"==e||"object"==e||"embed"==e||"video"==e||"audio"==e)&&(t.type||(t.type=e),t=tinymce.extend(i.map,t)),"script"==e){var a=r(i.map.src);if(!a)return;t={type:"script",source1:i.map.src,width:a.width,height:a.height}}"source"==e&&(t.source1?t.source2||(t.source2=i.map.src):t.source1=i.map.src),"img"!=e||t.poster||(t.poster=i.map.src)}}).parse(e),t.source1=t.source1||t.src||t.data,t.source2=t.source2||"",t.poster=t.poster||"",t}function s(t){return t.getAttribute("data-mce-object")?n(e.serializer.serialize(t,{selection:!0})):{}}function m(e,t,i){function r(e,t){var i,r,a,o;for(i in t)if(a=""+t[i],e.map[i])for(r=e.length;r--;)o=e[r],o.name==i&&(a?(e.map[i]=a,o.value=a):(delete e.map[i],e.splice(r,1)));else a&&(e.push({name:i,value:a}),e.map[i]=a)}var a,o=new tinymce.html.Writer,c=0;return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!0,special:"script,noscript",comment:function(e){o.comment(e)},cdata:function(e){o.cdata(e)},text:function(e,t){o.text(e,t)},start:function(e,n,s){switch(e){case"video":case"object":case"embed":case"img":case"iframe":r(n,{width:t.width,height:t.height})}if(i)switch(e){case"video":r(n,{poster:t.poster,src:""}),t.source2&&r(n,{src:""});break;case"iframe":r(n,{src:t.source1});break;case"source":if(c++,2>=c&&(r(n,{src:t["source"+c],type:t["source"+c+"mime"]}),!t["source"+c]))return;break;case"img":if(!t.poster)return;a=!0}o.start(e,n,s)},end:function(e){if("video"==e&&i)for(var n=1;2>=n;n++)if(t["source"+n]){var s=[];s.map={},n>c&&(r(s,{src:t["source"+n],type:t["source"+n+"mime"]}),o.start("source",s,!0))}if(t.poster&&"object"==e&&i&&!a){var m=[];m.map={},r(m,{src:t.poster,width:t.width,height:t.height}),o.start("img",m,!0)}o.end(e)}},new tinymce.html.Schema({})).parse(e),o.getContent()}var d=[{regex:/youtu\.be\/([a-z1-9.-_]+)/,type:"iframe",w:425,h:350,url:"http://www.youtube.com/embed/$1"},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:425,h:350,url:"http://www.youtube.com/embed/$2"},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"http://player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc"},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'http://maps.google.com/maps/ms?msid=$2&output=embed"'}];e.on("ResolveName",function(e){var t;1==e.target.nodeType&&(t=e.target.getAttribute("data-mce-object"))&&(e.name=t)}),e.on("preInit",function(){var t=e.schema.getSpecialElements();tinymce.each("video audio iframe object".split(" "),function(e){t[e]=new RegExp("]*>","gi")}),e.schema.addValidElements("object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]");var i=e.schema.getBoolAttrs();tinymce.each("webkitallowfullscreen mozallowfullscreen allowfullscreen".split(" "),function(e){i[e]={}}),e.parser.addNodeFilter("iframe,video,audio,object,embed,script",function(t,i){for(var a,o,c,n,s,m,d,u,l=t.length;l--;)if(o=t[l],"script"!=o.name||(u=r(o.attr("src")))){for(c=new tinymce.html.Node("img",1),c.shortEnded=!0,u&&(u.width&&o.attr("width",u.width.toString()),u.height&&o.attr("height",u.height.toString())),m=o.attributes,a=m.length;a--;)n=m[a].name,s=m[a].value,"width"!==n&&"height"!==n&&"style"!==n&&(("data"==n||"src"==n)&&(s=e.convertURL(s,n)),c.attr("data-mce-p-"+n,s));d=o.firstChild&&o.firstChild.value,d&&(c.attr("data-mce-html",escape(d)),c.firstChild=null),c.attr({width:o.attr("width")||"300",height:o.attr("height")||("audio"==i?"30":"150"),style:o.attr("style"),src:tinymce.Env.transparentSrc,"data-mce-object":i,"class":"mce-object mce-object-"+i}),o.replace(c)}}),e.serializer.addAttributeFilter("data-mce-object",function(e,t){for(var i,r,a,o,c,n,s,m=e.length;m--;){for(i=e[m],s=i.attr(t),r=new tinymce.html.Node(s,1),"audio"!=s&&"script"!=s&&r.attr({width:i.attr("width"),height:i.attr("height")}),r.attr({style:i.attr("style")}),o=i.attributes,a=o.length;a--;){var d=o[a].name;0===d.indexOf("data-mce-p-")&&r.attr(d.substr(11),o[a].value)}"script"==s&&r.attr("type","text/javascript"),c=i.attr("data-mce-html"),c&&(n=new tinymce.html.Node("#text",3),n.raw=!0,n.value=unescape(c),r.append(n)),i.replace(r)}})}),e.on("ObjectSelected",function(e){var t=e.target.getAttribute("data-mce-object");("audio"==t||"script"==t)&&e.preventDefault()}),e.on("objectResized",function(e){var t,i=e.target;i.getAttribute("data-mce-object")&&(t=i.getAttribute("data-mce-html"),t&&(t=unescape(t),i.setAttribute("data-mce-html",escape(m(t,{width:e.width,height:e.height})))))}),e.addButton("media",{tooltip:"Insert/edit video",onclick:a,stateSelector:"img[data-mce-object=video]"}),e.addMenuItem("media",{icon:"media",text:"Insert video",onclick:a,context:"insert",prependToContext:!0})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/nonbreaking/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/nonbreaking/plugin.min.js new file mode 100644 index 0000000..866339c --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/nonbreaking/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("nonbreaking",function(e){var t=e.getParam("nonbreaking_force_tab");if(e.addCommand("mceNonBreaking",function(){e.insertContent(e.plugins.visualchars&&e.plugins.visualchars.state?' ':" ")}),e.addButton("nonbreaking",{title:"Insert nonbreaking space",cmd:"mceNonBreaking"}),e.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),t){var n=+t>1?+t:3;e.on("keydown",function(t){if(9==t.keyCode){if(t.shiftKey)return;t.preventDefault();for(var i=0;n>i;i++)e.execCommand("mceNonBreaking")}})}}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/noneditable/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/noneditable/plugin.min.js new file mode 100644 index 0000000..aa642de --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(e){function t(e){var t;if(1===e.nodeType){if(t=e.getAttribute(u),t&&"inherit"!==t)return t;if(t=e.contentEditable,"inherit"!==t)return t}return null}function n(e){for(var n;e;){if(n=t(e))return"false"===n?e:null;e=e.parentNode}}function r(){function r(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function a(e){var t;if(e)for(t=new f(e,e),e=t.current();e;e=t.next())if(3===e.nodeType)return e}function i(n,r){var a,i;return"false"===t(n)&&u.isBlock(n)?void s.select(n):(i=u.createRng(),"true"===t(n)&&(n.firstChild||n.appendChild(e.getDoc().createTextNode(" ")),n=n.firstChild,r=!0),a=u.create("span",{id:g,"data-mce-bogus":!0},m),r?n.parentNode.insertBefore(a,n):u.insertAfter(a,n),i.setStart(a.firstChild,1),i.collapse(!0),s.setRng(i),a)}function o(e){var t,n,i,o;if(e)t=s.getRng(!0),t.setStartBefore(e),t.setEndBefore(e),n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0),s.setRng(t);else for(i=r(s.getStart());(e=u.get(g))&&e!==o;)i!==e&&(n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0)),o=e}function l(){function e(e,n){var r,a,i,o,l;if(r=d.startContainer,a=d.startOffset,3==r.nodeType){if(l=r.nodeValue.length,a>0&&l>a||(n?a==l:0===a))return}else{if(!(a0?a-1:a;r=r.childNodes[u],r.hasChildNodes()&&(r=r.firstChild)}for(i=new f(r,e);o=i[n?"prev":"next"]();){if(3===o.nodeType&&o.nodeValue.length>0)return;if("true"===t(o))return o}return e}var r,a,l,d,u;o(),l=s.isCollapsed(),r=n(s.getStart()),a=n(s.getEnd()),(r||a)&&(d=s.getRng(!0),l?(r=r||a,(u=e(r,!0))?i(u,!0):(u=e(r,!1))?i(u,!1):s.select(r)):(d=s.getRng(!0),r&&d.setStartBefore(r),a&&d.setEndAfter(a),s.setRng(d)))}function d(a){function i(e,t){for(;e=e[t?"previousSibling":"nextSibling"];)if(3!==e.nodeType||e.nodeValue.length>0)return e}function d(e,t){s.select(e),s.collapse(t)}function g(a){function i(e){for(var t=d;t;){if(t===e)return;t=t.parentNode}u.remove(e),l()}function o(){var r,o,l=e.schema.getNonEmptyElements();for(o=new tinymce.dom.TreeWalker(d,e.getBody());(r=a?o.prev():o.next())&&!l[r.nodeName.toLowerCase()]&&!(3===r.nodeType&&tinymce.trim(r.nodeValue).length>0);)if("false"===t(r))return i(r),!0;return n(r)?!0:!1}var f,d,c,g;if(s.isCollapsed()){if(f=s.getRng(!0),d=f.startContainer,c=f.startOffset,d=r(d)||d,g=n(d))return i(g),!1;if(3==d.nodeType&&(a?c>0:ch||h>124)&&h!=c.DELETE&&h!=c.BACKSPACE){if((tinymce.isMac?a.metaKey:a.ctrlKey)&&(67==h||88==h||86==h))return;if(a.preventDefault(),h==c.LEFT||h==c.RIGHT){var y=h==c.LEFT;if(e.dom.isBlock(m)){var T=y?m.previousSibling:m.nextSibling,C=new f(T,T),b=y?C.prev():C.next();d(b,!y)}else d(m,y)}}else if(h==c.LEFT||h==c.RIGHT||h==c.BACKSPACE||h==c.DELETE){if(p=r(v)){if(h==c.LEFT||h==c.BACKSPACE)if(m=i(p,!0),m&&"false"===t(m)){if(a.preventDefault(),h!=c.LEFT)return void u.remove(m);d(m,!0)}else o(p);if(h==c.RIGHT||h==c.DELETE)if(m=i(p),m&&"false"===t(m)){if(a.preventDefault(),h!=c.RIGHT)return void u.remove(m);d(m,!1)}else o(p)}if((h==c.BACKSPACE||h==c.DELETE)&&!g(h==c.BACKSPACE))return a.preventDefault(),!1}}var u=e.dom,s=e.selection,g="mce_noneditablecaret",m="";e.on("mousedown",function(n){var r=e.selection.getNode();"false"===t(r)&&r==n.target&&l()}),e.on("mouseup keyup",l),e.on("keydown",d)}function a(t){var n=l.length,r=t.content,a=tinymce.trim(o);if("raw"!=t.format){for(;n--;)r=r.replace(l[n],function(t){var n=arguments,i=n[n.length-2];return i>0&&'"'==r.charAt(i-1)?t:''+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+""});t.content=r}}var i,o,l,f=tinymce.dom.TreeWalker,d="contenteditable",u="data-mce-"+d,c=tinymce.util.VK;i=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",o=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",l=e.getParam("noneditable_regexp"),l&&!l.length&&(l=[l]),e.on("PreInit",function(){r(),l&&e.on("BeforeSetContent",a),e.parser.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)n=e[r],t=" "+n.attr("class")+" ",-1!==t.indexOf(i)?n.attr(u,"true"):-1!==t.indexOf(o)&&n.attr(u,"false")}),e.serializer.addAttributeFilter(u,function(e){for(var t,n=e.length;n--;)t=e[n],l&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):(t.attr(d,null),t.attr(u,null))}),e.parser.addAttributeFilter(d,function(e){for(var t,n=e.length;n--;)t=e[n],t.attr(u,t.attr(d)),t.attr(d,null)})}),e.on("drop",function(e){n(e.target)&&e.preventDefault()})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/pagebreak/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 0000000..e224cb4 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(e){var a="mce-pagebreak",t=e.getParam("pagebreak_separator",""),n=new RegExp(t.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),r='';e.addCommand("mcePageBreak",function(){e.settings.pagebreak_split_block?e.insertContent("

    "+r+"

    "):e.insertContent(r)}),e.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),e.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),e.on("ResolveName",function(t){"IMG"==t.target.nodeName&&e.dom.hasClass(t.target,a)&&(t.name="pagebreak")}),e.on("click",function(t){t=t.target,"IMG"===t.nodeName&&e.dom.hasClass(t,a)&&e.selection.select(t)}),e.on("BeforeSetContent",function(e){e.content=e.content.replace(n,r)}),e.on("PreInit",function(){e.serializer.addNodeFilter("img",function(a){for(var n,r,c=a.length;c--;)if(n=a[c],r=n.attr("class"),r&&-1!==r.indexOf("mce-pagebreak")){var o=n.parent;if(e.schema.getBlockElements()[o.name]&&e.settings.pagebreak_split_block){o.type=3,o.value=t,o.raw=!0,n.remove();continue}n.type=3,n.value=t,n.raw=!0}})})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/paste/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/paste/plugin.min.js new file mode 100644 index 0000000..c099330 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i"),t&&/^(PRE|DIV)$/.test(t.nodeName)||!o?e=n.filter(e,[[/\n/g,"
    "]]):(e=n.filter(e,[[/\n\n/g,"

    "+a],[/^(.*<\/p>)(

    )$/,a+"$1"],[/\n/g,"
    "]]),-1!=e.indexOf("

    ")&&(e=a+e)),i(e)}function a(){var t=r.dom,n=r.getBody(),i=r.dom.getViewPort(r.getWin()),o=i.y,a=20;if(h=r.selection.getRng(),r.inline){var s=r.selection.getScrollContainer();s&&(o=s.scrollTop)}if(h.getClientRects){var l=h.getClientRects();l.length&&(a=o+(l[0].top-t.getPos(n).y))}m=t.add(r.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"1",style:"position: absolute; top: "+a+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},v),(e.ie||e.gecko)&&t.setStyle(m,"left","rtl"==t.getStyle(n,"direction",!0)?65535:-65535),t.bind(m,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),m.focus(),r.selection.select(m,!0)}function s(){if(m){for(var e;e=r.dom.get("mcepastebin");)r.dom.remove(e),r.dom.unbind(e);h&&r.selection.setRng(h)}y=!1,m=h=null}function l(){var e=v,t,n;for(t=r.dom.select("div[id=mcepastebin]"),n=t.length;n--;){var i=t[n].innerHTML;e==v&&(e=""),i.length>e.length&&(e=i)}return e}function c(e){var t={};if(e&&e.types){t["text/plain"]=e.getData("Text");for(var n=0;nl?n&&(n=n.parent.parent):(r=n,n=null)),n&&n.name==a?n.append(e):(r=r||n,n=new i(a,1),s>1&&n.attr("start",""+s),e.wrap(n)),e.name="li",t.value="";var c=t.next;c&&3==c.type&&(c.value=c.value.replace(/^\u00a0+/,"")),l>o&&r&&r.lastChild.append(n),o=l}for(var n,r,o=1,a=e.getAll("p"),s=0;s/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var h=l.paste_word_valid_elements;h||(h="@[style],-strong/b,-em/i,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-table,-tr,-td[colspan|rowspan],-th,-thead,-tfoot,-tbody,-a[href|name],sub,sup,strike,br");var g=new n({valid_elements:h}),v=new t({},g);v.addAttributeFilter("style",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("style",u(n,n.attr("style"))),"span"!=n.name||n.attributes.length||n.unwrap()}),v.addNodeFilter("a",function(e){for(var t=e.length,n,r,i;t--;)n=e[t],r=n.attr("href"),i=n.attr("name"),r&&0===r.indexOf("file://")&&(r=r.split("#")[1],r&&(r="#"+r)),r||i?n.attr({href:r,name:i}):n.unwrap()});var y=v.parse(f);d(y),c.content=new r({},g).serialize(y)}})}return s.isWordContent=a,s}),r(y,[p,c,h,l],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){return e=r.filter(e,[/^[\s\S]*|[\s\S]*$/g,[/\u00a0<\/span>/g,"\xa0"],/
    $/])}function s(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp("(?:
     [\\s\\r\\n]+|
    )*(<\\/?("+o.join("|")+")[^>]*>)(?:
     [\\s\\r\\n]+|
    )*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/

    /g,"

    "],[/
    /g," "],[/

    /g,"
    "]])}function l(e){return(i.settings.paste_remove_styles||i.settings.paste_remove_styles_if_webkit!==!1)&&(e=e.replace(/ style=\"[^\"]+\"/g,"")),e}e.webkit&&(o(l),o(a)),e.ie&&o(s)}}),r(b,[C,f,h,y],function(e,t,n,r){var i;e.add("paste",function(e){function o(){"text"==s.pasteFormat?(this.active(!1),s.pasteFormat="html"):(s.pasteFormat="text",this.active(!0),i||(e.windowManager.alert("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),i=!0))}var a=this,s,l=e.settings;a.clipboard=s=new t(e),a.quirks=new r(e),a.wordFilter=new n(e),e.settings.paste_as_text&&(a.clipboard.pasteFormat="text"),l.paste_preprocess&&e.on("PastePreProcess",function(e){l.paste_preprocess.call(a,a,e)}),l.paste_postprocess&&e.on("PastePostProcess",function(e){l.paste_postprocess.call(a,a,e)}),e.addCommand("mceInsertClipboardContent",function(e,t){t.content&&a.clipboard.pasteHtml(t.content),t.text&&a.clipboard.pasteText(t.text)}),e.paste_block_drop&&e.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),e.settings.paste_data_images||e.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),e.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:o,active:"text"==a.clipboard.pasteFormat}),e.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:s.pasteFormat,onclick:o})})}),a([l,f,h,y,b])}(this); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/preview/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 0000000..8a24058 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(e){var t=e.settings;e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:'',buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var i,n=this.getEl("body").firstChild.contentWindow.document,a="";tinymce.each(e.contentCSS,function(t){a+=''});var d=t.body_id||"tinymce";-1!=d.indexOf("=")&&(d=e.getParam("body_id","","hash"),d=d[e.id]||d);var r=t.body_class||"";-1!=r.indexOf("=")&&(r=e.getParam("body_class","","hash"),r=r[e.id]||""),i=""+a+""+''+e.getContent()+""+"",n.open(),n.write(i),n.close()}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/print/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/print/plugin.min.js new file mode 100644 index 0000000..abc37b5 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(t){t.addCommand("mcePrint",function(){t.getWin().print()}),t.addButton("print",{title:"Print",cmd:"mcePrint"}),t.addShortcut("Ctrl+P","","mcePrint"),t.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Ctrl+P",context:"file"})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/save/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/save/plugin.min.js new file mode 100644 index 0000000..bd50cec --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(e){function t(){var t,n;return t=tinymce.DOM.getParent(e.id,"form"),!e.getParam("save_enablewhendirty",!0)||e.isDirty()?(tinymce.triggerSave(),(n=e.getParam("save_onsavecallback"))?(e.execCallback("save_onsavecallback",e)&&(e.startContent=tinymce.trim(e.getContent({format:"raw"})),e.nodeChanged()),void 0):(t?(e.isNotDirty=!0,(!t.onsubmit||t.onsubmit())&&("function"==typeof t.submit?t.submit():e.windowManager.alert("Error: Form submit field collision.")),e.nodeChanged()):e.windowManager.alert("Error: No form element found."),void 0)):void 0}function n(){var t,n=tinymce.trim(e.startContent);return(t=e.getParam("save_oncancelcallback"))?(e.execCallback("save_oncancelcallback",e),void 0):(e.setContent(n),e.undoManager.clear(),e.nodeChanged(),void 0)}function i(){var t=this;e.on("nodeChange",function(){t.disabled(e.getParam("save_enablewhendirty",!0)&&!e.isDirty())})}e.addCommand("mceSave",t),e.addCommand("mceCancel",n),e.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:i}),e.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:i}),e.addShortcut("ctrl+s","","mceSave")}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/searchreplace/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/searchreplace/plugin.min.js new file mode 100644 index 0000000..7ffaf46 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function e(e,t,n,a,r){function i(e,t){if(t=t||0,!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var n=e.index;if(t>0){var a=e[t];if(!a)throw"Invalid capture group";n+=e[0].indexOf(a),e[0]=a}return[n,n+e[0].length,[e[0]]]}function d(e){var t;if(3===e.nodeType)return e.data;if(h[e.nodeName]&&!u[e.nodeName])return"";if(t="",(u[e.nodeName]||m[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=d(e);while(e=e.nextSibling);return t}function o(e,t,n){var a,r,i,d,o=[],l=0,c=e,s=t.shift(),f=0;e:for(;;){if((u[c.nodeName]||m[c.nodeName])&&l++,3===c.nodeType&&(!r&&c.length+l>=s[1]?(r=c,d=s[1]-l):a&&o.push(c),!a&&c.length+l>s[0]&&(a=c,i=s[0]-l),l+=c.length),a&&r){if(c=n({startNode:a,startNodeIndex:i,endNode:r,endNodeIndex:d,innerNodes:o,match:s[2],matchIndex:f}),l-=r.length-d,a=null,r=null,o=[],s=t.shift(),f++,!s)break}else{if((!h[c.nodeName]||u[c.nodeName])&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function l(e){var t;if("function"!=typeof e){var n=e.nodeType?e:f.createElement(e);t=function(e,t){var a=n.cloneNode(!1);return a.setAttribute("data-mce-index",t),e&&a.appendChild(f.createTextNode(e)),a}}else t=e;return function(e){var n,a,r,i=e.startNode,d=e.endNode,o=e.matchIndex;if(i===d){var l=i;r=l.parentNode,e.startNodeIndex>0&&(n=f.createTextNode(l.data.substring(0,e.startNodeIndex)),r.insertBefore(n,l));var c=t(e.match[0],o);return r.insertBefore(c,l),e.endNodeIndexh;++h){var g=e.innerNodes[h],p=t(g.data,o);g.parentNode.replaceChild(p,g),u.push(p)}var x=t(d.data.substring(0,e.endNodeIndex),o);return r=i.parentNode,r.insertBefore(n,i),r.insertBefore(s,i),r.removeChild(i),r=d.parentNode,r.insertBefore(x,d),r.insertBefore(a,d),r.removeChild(d),x}}var c,s,f,u,h,m,g=[],p=0;if(f=t.ownerDocument,u=r.getBlockElements(),h=r.getWhiteSpaceElements(),m=r.getShortEndedElements(),s=d(t)){if(e.global)for(;c=e.exec(s);)g.push(i(c,a));else c=s.match(e),g.push(i(c,a));return g.length&&(p=g.length,o(t,g,l(n))),p}}function t(t){function n(){function e(){r.statusbar.find("#next").disabled(!d(s+1).length),r.statusbar.find("#prev").disabled(!d(s-1).length)}function n(){tinymce.ui.MessageBox.alert("Could not find the specified string.",function(){r.find("#find")[0].focus()})}var a={},r=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){t.focus(),c.done()},onSubmit:function(t){var i,o,l,f;return t.preventDefault(),o=r.find("#case").checked(),f=r.find("#words").checked(),l=r.find("#find").value(),l.length?a.text==l&&a.caseState==o&&a.wholeWord==f?0===d(s+1).length?(n(),void 0):(c.next(),e(),void 0):(i=c.find(l,o,f),i||n(),r.statusbar.items().slice(1).disabled(0===i),e(),a={text:l,caseState:o,wholeWord:f},void 0):(c.done(!1),r.statusbar.items().slice(1).disabled(!0),void 0)},buttons:[{text:"Find",onclick:function(){r.submit()}},{text:"Replace",disabled:!0,onclick:function(){c.replace(r.find("#replace").value())||(r.statusbar.items().slice(1).disabled(!0),s=-1,a={})}},{text:"Replace all",disabled:!0,onclick:function(){c.replace(r.find("#replace").value(),!0,!0),r.statusbar.items().slice(1).disabled(!0),a={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){c.prev(),e()}},{text:"Next",name:"next",disabled:!0,onclick:function(){c.next(),e()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:t.selection.getNode().src},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow()}function a(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function r(n){var a,r;return r=t.dom.create("span",{"data-mce-bogus":1}),r.className="mce-match-marker",a=t.getBody(),c.done(!1),e(n,a,r,!1,t.schema)}function i(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function d(e){var n,r=[];if(n=tinymce.toArray(t.getBody().getElementsByTagName("span")),n.length)for(var i=0;is&&f[o].setAttribute("data-mce-index",m-1)}return t.undoManager.add(),s=p,n?(g=d(p+1).length>0,c.next()):(g=d(p-1).length>0,c.prev()),!r&&g},c.done=function(e){var n,r,d,o;for(r=tinymce.toArray(t.getBody().getElementsByTagName("span")),n=0;n=d.end?(i=c,a=d.end-l):r&&s.push(c),!r&&c.length+l>d.start&&(r=c,o=d.start-l),l+=c.length),r&&i){if(c=n({startNode:r,startNodeIndex:o,endNode:i,endNodeIndex:a,innerNodes:s,match:d.text,matchIndex:u}),l-=i.length-a,r=null,i=null,s=[],d=t.shift(),u++,!d)break}else{if((!k[c.nodeName]||N[c.nodeName])&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function o(e){function t(t,n){var r=x[n];r.stencil||(r.stencil=e(r));var i=r.stencil.cloneNode(!1);return i.setAttribute("data-mce-index",n),t&&i.appendChild(_.doc.createTextNode(t)),i}return function n(e){var n,r,i,o=e.startNode,a=e.endNode,s=e.matchIndex,l=_.doc;if(o===a){var c=o;i=c.parentNode,e.startNodeIndex>0&&(n=l.createTextNode(c.data.substring(0,e.startNodeIndex)),i.insertBefore(n,c));var d=t(e.match,s);return i.insertBefore(d,c),e.endNodeIndexp;++p){var h=e.innerNodes[p],g=t(h.data,s);h.parentNode.replaceChild(g,h),f.push(g)}var v=t(a.data.substring(0,e.endNodeIndex),s);return i=o.parentNode,i.insertBefore(n,o),i.insertBefore(u,o),i.removeChild(o),i=a.parentNode,i.insertBefore(v,a),i.insertBefore(r,a),i.removeChild(a),v}}function a(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function s(t){var n=e.getElementsByTagName("*"),r=[];t="number"==typeof t?""+t:null;for(var i=0;it&&e(x[t],t)!==!1;t++);return this}function u(t){return x.length&&i(e,x,o(t)),this}function f(e,t){if(w&&e.global)for(;C=e.exec(w);)x.push(n(C,t));return this}function p(e){var t,n=s(e?l(e):null);for(t=n.length;t--;)a(n[t]);return this}function m(e){return x[e.getAttribute("data-mce-index")]}function h(e){return s(l(e))[0]}function g(e,t,n){return x.push({start:e,end:e+t,text:w.substr(e,t),data:n}),this}function v(e){var n=s(l(e)),r=t.dom.createRng();return r.setStartBefore(n[0]),r.setEndAfter(n[n.length-1]),r}function y(e,n){var r=v(e);return r.deleteContents(),n.length>0&&r.insertNode(t.dom.doc.createTextNode(n)),r}function b(){return x.splice(0,x.length),p(),this}var C,x=[],w,_=t.dom,N,k,E;return N=t.schema.getBlockElements(),k=t.schema.getWhiteSpaceElements(),E=t.schema.getShortEndedElements(),w=r(e),{text:w,matches:x,each:d,filter:c,reset:b,matchFromElement:m,elementFromMatch:h,find:f,add:g,wrap:u,unwrap:p,replace:y,rangeFromMatch:v,indexOf:l}}}),r(c,[l,d,u,f,p,m,h],function(e,t,n,r,i,o,a){t.add("spellchecker",function(t,s){function l(){return y.textMatcher||(y.textMatcher=new e(t.getBody(),t)),y.textMatcher}function c(e,t){var r=[];return n.each(t,function(e){r.push({selectable:!0,text:e.name,data:e.value})}),r}function d(e){for(var t in e)return!1;return!0}function u(e){var o=[],a=b[e.text];n.each(a,function(n){o.push({text:n,onclick:function(){var r=l().replace(e,n);r.collapse(!1),t.selection.setRng(r),p()}})}),o.push.apply(o,[{text:"-"},{text:"Ignore",onclick:function(){m(e)}},{text:"Ignore all",onclick:function(){m(e,!0)}},{text:"Finish",onclick:h}]),x=new r({items:o,context:"contextmenu",onautohide:function(e){-1!=e.target.className.indexOf("spellchecker")&&e.preventDefault()},onhide:function(){x.remove(),x=null}}),x.renderTo(document.body);var s=l().elementFromMatch(e),c=i.DOM.getPos(t.getContentAreaContainer()),d=t.dom.getPos(s),u=t.dom.getRoot();"BODY"==u.nodeName?(d.x-=u.ownerDocument.documentElement.scrollLeft||u.scrollLeft,d.y-=u.ownerDocument.documentElement.scrollTop||u.scrollTop):(d.x-=u.scrollLeft,d.y-=u.scrollTop),c.x+=d.x,c.y+=d.y,x.moveTo(c.x,c.y+s.offsetHeight)}function f(){function e(e){return t.setProgressState(!1),d(e)?(t.windowManager.alert("No misspellings found"),void(C=!1)):(b=e,l().filter(function(t){return!!e[t.text]}).wrap(function(){return t.dom.create("span",{"class":"mce-spellchecker-word","data-mce-bogus":1})}),void t.fire("SpellcheckStart"))}function n(e,n,r){o.sendRPC({url:new a(s).toAbsolute(w.spellchecker_rpc_url),method:e,params:{lang:w.spellchecker_language||"en",words:n},success:function(e){r(e)},error:function(e,n){e="JSON Parse error."==e?"Non JSON response:"+n.responseText:"Error: "+e,t.windowManager.alert(e),t.setProgressState(!1),h()}})}var r=[],i={};if(C)return void h();h(),C=!0;var c=t.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e]+',"g");l().find(c).each(function(e){var t=e.text;if(!i[t]){if(/^\d+$/.test(t)||1==t.length)return;r.push(t),i[t]=!0}}),t.setProgressState(!0);var u=w.spellchecker_callback||n;u("spellcheck",r,e)}function p(){t.dom.select("span.mce-spellchecker-word").length||h()}function m(e,n){t.selection.collapse(),n?l().each(function(t){t.text==e.text&&l().unwrap(t)}):l().unwrap(e),p()}function h(){l().reset(),y.textMatcher=null,C&&(C=!1,t.fire("SpellcheckEnd"))}function g(e){var t=w.spellchecker_language;e.control.items().each(function(e){e.active(e.settings.data===t)})}var v,y=this,b,C,x,w=t.settings,_=w.spellchecker_languages||"English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr_FR,German=de,Italian=it,Polish=pl,Portuguese=pt_BR,Spanish=es,Swedish=sv";v=c("Language",n.map(_.split(","),function(e){var t=e.split("=");return{name:t[0],value:t[1]}})),t.on("click",function(e){if("mce-spellchecker-word"==e.target.className){e.preventDefault();var n=l().matchFromElement(e.target);t.selection.setRng(l().rangeFromMatch(n)),u(n)}}),t.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:f,selectable:!0,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(C)})}});var N={tooltip:"Spellcheck",onclick:f,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(C)})}};v.length>1&&(N.type="splitbutton",N.menu=v,N.onshow=g,N.onselect=function(e){w.spellchecker_language=e.control.settings.data}),t.addButton("spellchecker",N),t.addCommand("mceSpellCheck",f),t.on("remove",function(){x&&(x.remove(),x=null)}),this.getTextMatcher=l,w.spellchecker_language=w.spellchecker_language||w.language||"en"})}),a([l,c])}(this); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/tabfocus/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/tabfocus/plugin.min.js new file mode 100644 index 0000000..68fe35e --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/tabfocus/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("tabfocus",function(e){function n(e){9!==e.keyCode||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}function t(n){function t(n){function t(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&t(e.parentNode)}function r(e){return e.tabIndex||"INPUT"==e.nodeName||"TEXTAREA"==e.nodeName}function c(e){return!r(e)&&"-1"!=e.getAttribute("tabindex")&&t(e)}if(u=i.select(":input:enabled,*[tabindex]:not(iframe)"),o(u,function(n,t){return n.id==e.id?(a=t,!1):void 0}),n>0){for(d=a+1;d=0;d--)if(c(u[d]))return u[d];return null}var a,u,c,d;if(!(9!==n.keyCode||n.ctrlKey||n.altKey||n.metaKey)&&(c=r(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==c.length&&(c[1]=c[0],c[0]=":prev"),u=n.shiftKey?":prev"==c[0]?t(-1):i.get(c[0]):":next"==c[1]?t(1):i.get(c[1]))){var y=tinymce.get(u.id||u.name);u.id&&y?y.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),u.focus()},10),n.preventDefault()}}var i=tinymce.DOM,o=tinymce.each,r=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null)}),e.on("keyup",n),tinymce.Env.gecko?e.on("keypress keydown",t):e.on("keydown",t)}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/table/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/table/plugin.min.js new file mode 100644 index 0000000..d041cae --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/table/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i "+t+" tr",o);r(i,function(i,o){o+=e,r(H.select("> td, > th",i),function(e,r){var i,a,s,l;if(R[o])for(;R[o][r];)r++;for(s=n(e,"rowspan"),l=n(e,"colspan"),a=o;o+s>a;a++)for(R[a]||(R[a]=[]),i=r;r+l>i;i++)R[a][i]={part:t,real:a==o&&i==r,elm:e,rowspan:s,colspan:l}})}),e+=i.length})}function s(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function l(e,t){var n;return n=R[t],n?n[e]:void 0}function c(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function d(e){return e&&(H.hasClass(e.elm,"mce-item-selected")||e==L)}function u(){var e=[];return r(o.rows,function(t){r(t.cells,function(n){return H.hasClass(n,"mce-item-selected")||n==L.elm?(e.push(t),!1):void 0})}),e}function f(){var e=H.createRng();e.setStartAfter(o),e.setEndAfter(o),D.setRng(e),H.remove(o)}function p(n){var o,a={};return i.settings.table_clone_elements!==!1&&(a=e.makeMap((i.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(n,function(e){var i;return 3==e.nodeType?(r(H.getParents(e.parentNode,null,n).reverse(),function(e){a[e.nodeName]&&(e=s(e,!1),o?i&&i.appendChild(e):o=i=e,i=e)}),i&&(i.innerHTML=t.ie?" ":'
    '),!1):void 0},"childNodes"),n=s(n,!1),c(n,"rowSpan",1),c(n,"colSpan",1),o?n.appendChild(o):t.ie||(n.innerHTML='
    '),n}function m(){var e=H.createRng(),t;return r(H.select("tr",o),function(e){0===e.cells.length&&H.remove(e)}),0===H.select("tr",o).length?(e.setStartBefore(o),e.setEndBefore(o),D.setRng(e),H.remove(o),void 0):(r(H.select("thead,tbody,tfoot",o),function(e){0===e.rows.length&&H.remove(e)}),a(),t=R[Math.min(R.length-1,A.y)],t&&(D.select(t[Math.min(t.length-1,A.x)].elm,!0),D.collapse(!0)),void 0)}function h(e,t,n,r){var i,o,a,s,l;for(i=R[t][e].elm.parentNode,a=1;n>=a;a++)if(i=H.getNext(i,"tr")){for(o=e;o>=0;o--)if(l=R[t+a][o].elm,l.parentNode==i){for(s=1;r>=s;s++)H.insertAfter(p(l),l);break}if(-1==o)for(s=1;r>=s;s++)i.insertBefore(p(i.cells[0]),i.cells[0])}}function g(){r(R,function(e,t){r(e,function(e,r){var i,o,a;if(d(e)&&(e=e.elm,i=n(e,"colspan"),o=n(e,"rowspan"),i>1||o>1)){for(c(e,"rowSpan",1),c(e,"colSpan",1),a=0;i-1>a;a++)H.insertAfter(p(e),e);h(r,t,o-1,i)}})})}function v(t,n,i){var o,s,u,f,p,h,v,y,b,C,x;if(t?(o=E(t),s=o.x,u=o.y,f=s+(n-1),p=u+(i-1)):(A=B=null,r(R,function(e,t){r(e,function(e,n){d(e)&&(A||(A={x:n,y:t}),B={x:n,y:t})})}),s=A.x,u=A.y,f=B.x,p=B.y),y=l(s,u),b=l(f,p),y&&b&&y.part==b.part){for(g(),a(),y=l(s,u).elm,c(y,"colSpan",f-s+1),c(y,"rowSpan",p-u+1),v=u;p>=v;v++)for(h=s;f>=h;h++)R[v]&&R[v][h]&&(t=R[v][h].elm,t!=y&&(C=e.grep(t.childNodes),r(C,function(e){y.appendChild(e)}),C.length&&(C=e.grep(y.childNodes),x=0,r(C,function(e){"BR"==e.nodeName&&H.getAttrib(e,"data-mce-bogus")&&x++0&&R[t-1][a]&&(m=R[t-1][a].elm,h=n(m,"rowSpan"),h>1)){c(m,"rowSpan",h+1);continue}}else if(h=n(i,"rowspan"),h>1){c(i,"rowSpan",h+1);continue}f=p(i),c(f,"colSpan",i.colSpan),u.appendChild(f),o=i}u.hasChildNodes()&&(e?l.parentNode.insertBefore(u,l):H.insertAfter(u,l))}function b(e){var t,i;r(R,function(n){return r(n,function(n,r){return d(n)&&(t=r,e)?!1:void 0}),e?!t:void 0}),r(R,function(r,o){var a,s,l;r[t]&&(a=r[t].elm,a!=i&&(l=n(a,"colspan"),s=n(a,"rowspan"),1==l?e?(a.parentNode.insertBefore(p(a),a),h(t,o,s-1,l)):(H.insertAfter(p(a),a),h(t,o,s-1,l)):c(a,"colSpan",a.colSpan+1),i=a))})}function C(){var t=[];r(R,function(i){r(i,function(i,o){d(i)&&-1===e.inArray(t,o)&&(r(R,function(e){var t=e[o].elm,r;r=n(t,"colSpan"),r>1?c(t,"colSpan",r-1):H.remove(t)}),t.push(o))})}),m()}function x(){function e(e){var t,i,o;t=H.getNext(e,"tr"),r(e.cells,function(e){var t=n(e,"rowSpan");t>1&&(c(e,"rowSpan",t-1),i=E(e),h(i.x,i.y,1,1))}),i=E(e.cells[0]),r(R[i.y],function(e){var t;e=e.elm,e!=o&&(t=n(e,"rowSpan"),1>=t?H.remove(e):c(e,"rowSpan",t-1),o=e)})}var t;t=u(),r(t.reverse(),function(t){e(t)}),m()}function w(){var e=u();return H.remove(e),m(),e}function _(){var e=u();return r(e,function(t,n){e[n]=s(t,!0)}),e}function N(e,t){var n=u(),i=n[t?0:n.length-1],o=i.cells.length;e&&(r(R,function(e){var t;return o=0,r(e,function(e){e.real&&(o+=e.colspan),e.elm.parentNode==i&&(t=1)}),t?!1:void 0}),t||e.reverse(),r(e,function(e){var n,r=e.cells.length,a;for(n=0;r>n;n++)a=e.cells[n],c(a,"colSpan",1),c(a,"rowSpan",1);for(n=r;o>n;n++)e.appendChild(p(e.cells[r-1]));for(n=o;r>n;n++)H.remove(e.cells[n]);t?i.parentNode.insertBefore(e,i):H.insertAfter(e,i)}),H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function E(e){var t;return r(R,function(n,i){return r(n,function(n,r){return n.elm==e?(t={x:r,y:i},!1):void 0}),!t}),t}function k(e){A=E(e)}function S(){var e,t;return e=t=0,r(R,function(n,i){r(n,function(n,r){var o,a;d(n)&&(n=R[i][r],r>e&&(e=r),i>t&&(t=i),n.real&&(o=n.colspan-1,a=n.rowspan-1,o&&r+o>e&&(e=r+o),a&&i+a>t&&(t=i+a)))})}),{x:e,y:t}}function T(e){var t,n,r,i,o,a,s,l,c,d;if(B=E(e),A&&B){for(t=Math.min(A.x,B.x),n=Math.min(A.y,B.y),r=Math.max(A.x,B.x),i=Math.max(A.y,B.y),o=r,a=i,d=n;a>=d;d++)e=R[d][t],e.real||t-(e.colspan-1)=c;c++)e=R[n][c],e.real||n-(e.rowspan-1)=d;d++)for(c=t;r>=c;c++)e=R[d][c],e.real&&(s=e.colspan-1,l=e.rowspan-1,s&&c+s>o&&(o=c+s),l&&d+l>a&&(a=d+l));for(H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=n;a>=d;d++)for(c=t;o>=c;c++)R[d][c]&&H.addClass(R[d][c].elm,"mce-item-selected")}}var R,A,B,L,D=i.selection,H=D.dom;o=o||H.getParent(D.getStart(),"table"),a(),L=H.getParent(D.getStart(),"th,td"),L&&(A=E(L),B=S(),L=l(A.x,A.y)),e.extend(this,{deleteTable:f,split:g,merge:v,insertRow:y,insertCol:b,deleteCols:C,deleteRows:x,cutRows:w,copyRows:_,pasteRows:N,getPos:E,setStartCell:k,setEndCell:T})}}),r(u,[f,d,c],function(e,t,n){function r(e,t){return parseInt(e.getAttribute(t)||1,10)}var i=n.each;return function(n){function o(){function t(t){function o(e,r){var i=e?"previousSibling":"nextSibling",o=n.dom.getParent(r,"tr"),s=o[i];if(s)return g(n,r,s,e),t.preventDefault(),!0;var d=n.dom.getParent(o,"table"),u=o.parentNode,f=u.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var p=a(e,d,u,"tbody");if(null!==p)return l(e,p,r)}return c(e,o,i,d)}function a(e,t,r,i){var o=n.dom.select(">"+i,t),a=o.indexOf(r);if(e&&0===a||!e&&a===o.length-1)return s(e,t);if(-1===a){var l="thead"===r.tagName.toLowerCase()?0:o.length-1;return o[l]}return o[a+(e?-1:1)]}function s(e,t){var r=e?"thead":"tfoot",i=n.dom.select(">"+r,t);return 0!==i.length?i[0]:null}function l(e,r,i){var o=d(r,e);return o&&g(n,i,o,e),t.preventDefault(),!0}function c(e,r,i,a){var s=a[i];if(s)return u(s),!0;var l=n.dom.getParent(a,"td,th");if(l)return o(e,l,t);var c=d(r,!e);return u(c),t.preventDefault(),!1}function d(e,t){var r=e&&e[t?"lastChild":"firstChild"];return r&&"BR"===r.nodeName?n.dom.getParent(r,"td,th"):r}function u(e){n.selection.setCursorLocation(e,0)}function f(){return b==e.UP||b==e.DOWN}function p(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function m(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=r(n,"colspan");return t}function h(e,t){var n=0,o=0;return i(e.children,function(e,i){return n+=r(e,"colspan"),o=i,n>t?!1:void 0}),o}function g(e,t,r,i){var o=m(n.dom.getParent(t,"td,th")),a=h(r,o),s=r.childNodes[a],l=d(s,i);u(l||s)}function v(e){var t=n.selection.getNode(),r=n.dom.getParent(t,"td,th"),i=n.dom.getParent(e,"td,th");return r&&r!==i&&y(r,i)}function y(e,t){return n.dom.getParent(e,"TABLE")===n.dom.getParent(t,"TABLE")}var b=t.keyCode;if(f()&&p(n)){var C=n.selection.getNode();setTimeout(function(){v(C)&&o(!t.shiftKey&&b===e.UP,C,t)},0)}}n.on("KeyDown",function(e){t(e)})}function a(){function e(e,t){var n=t.ownerDocument,r=n.createRange(),i;return r.setStartBefore(t),r.setEnd(e.endContainer,e.endOffset),i=n.createElement("body"),i.appendChild(r.cloneContents()),0===i.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}n.on("KeyDown",function(t){var r,i,o=n.dom;(37==t.keyCode||38==t.keyCode)&&(r=n.selection.getRng(),i=o.getParent(r.startContainer,"table"),i&&n.getBody().firstChild==i&&e(r,i)&&(r=o.createRng(),r.setStartBefore(i),r.setEndBefore(i),n.selection.setRng(r),t.preventDefault()))})}function s(){n.on("KeyDown SetContent VisualAid",function(){var e;for(e=n.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&!e.getAttribute("data-mce-bogus"))break;e&&"TABLE"==e.nodeName&&(n.settings.forced_root_block?n.dom.add(n.getBody(),n.settings.forced_root_block,n.settings.forced_root_block_attrs,t.ie&&t.ie<11?" ":'
    '):n.dom.add(n.getBody(),"br",{"data-mce-bogus":"1"}))}),n.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&n.dom.remove(t)})}function l(){function e(e,t,n,r){var i=3,o=e.dom.getParent(t.startContainer,"TABLE"),a,s,l;return o&&(a=o.parentNode),s=t.startContainer.nodeType==i&&0===t.startOffset&&0===t.endOffset&&r&&("TR"==n.nodeName||n==a),l=("TD"==n.nodeName||"TH"==n.nodeName)&&!r,s||l}function t(){var t=n.selection.getRng(),r=n.selection.getNode(),i=n.dom.getParent(t.startContainer,"TD,TH");if(e(n,t,r,i)){i||(i=r);for(var o=i.lastChild;o.lastChild;)o=o.lastChild;t.setEnd(o,o.nodeValue.length),n.selection.setRng(t)}}n.on("KeyDown",function(){t()}),n.on("MouseDown",function(e){2!=e.button&&t()})}function c(){n.on("keydown",function(t){if((t.keyCode==e.DELETE||t.keyCode==e.BACKSPACE)&&!t.isDefaultPrevented()){var r=n.dom.getParent(n.selection.getStart(),"table");if(r){for(var i=n.dom.select("td,th",r),o=i.length;o--;)if(!n.dom.hasClass(i[o],"mce-item-selected"))return;t.preventDefault(),n.execCommand("mceTableDelete")}}})}c(),t.webkit&&(o(),l()),t.gecko&&(a(),s()),t.ie>10&&(a(),s())}}),r(p,[l,m,c],function(e,t,n){return function(r){function i(){r.getBody().style.webkitUserSelect="",d&&(r.dom.removeClass(r.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=!1)}function o(t){var n,i,o=t.target;if(l&&(s||o!=l)&&("TD"==o.nodeName||"TH"==o.nodeName)){i=a.getParent(o,"table"),i==c&&(s||(s=new e(r,i),s.setStartCell(l),r.getBody().style.webkitUserSelect="none"),s.setEndCell(o),d=!0),n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(u){}t.preventDefault()}}var a=r.dom,s,l,c,d=!0;return r.on("MouseDown",function(e){2!=e.button&&(i(),l=a.getParent(e.target,"td,th"),c=a.getParent(l,"table"))}),a.bind(r.getDoc(),"mouseover",o),r.on("remove",function(){a.unbind(r.getDoc(),"mouseover",o)}),r.on("MouseUp",function(){function e(e,r){var o=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return r?i.setStart(e,0):i.setEnd(e,e.nodeValue.length),void 0;if("BR"==e.nodeName)return r?i.setStartBefore(e):i.setEndBefore(e),void 0}while(e=r?o.next():o.prev())}var i,o=r.selection,d,u,f,p,m;if(l){if(s&&(r.getBody().style.webkitUserSelect=""),d=a.select("td.mce-item-selected,th.mce-item-selected"),d.length>0){i=a.createRng(),f=d[0],m=d[d.length-1],i.setStartBefore(f),i.setEndAfter(f),e(f,1),u=new t(f,a.getParent(d[0],"table"));do if("TD"==f.nodeName||"TH"==f.nodeName){if(!a.hasClass(f,"mce-item-selected"))break;p=f}while(f=u.next());e(p),o.setRng(i)}r.nodeChanged(),l=s=c=null}}),r.on("KeyUp",function(){i()}),{clear:i}}}),r(h,[l,u,p,c,m,d,g],function(e,t,n,r,i,o,a){function s(r){function i(e){return e?e.replace(/px$/,""):""}function a(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function s(e){l("left center right".split(" "),function(t){r.formatter.remove("align"+t,{},e)})}function c(){var e=r.dom,t,n;t=e.getParent(r.selection.getStart(),"table"),n={width:i(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:i(e.getStyle(t,"height")||e.getAttrib(t,"height")),cellspacing:e.getAttrib(t,"cellspacing"),cellpadding:e.getAttrib(t,"cellpadding"),border:e.getAttrib(t,"border"),caption:!!e.select("caption",t)[0]},l("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Table properties",items:{type:"form",layout:"grid",columns:2,data:n,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"},{label:"Alignment",minWidth:90,name:"align",type:"listbox",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var n=this.toJSON(),i;r.undoManager.transact(function(){r.dom.setAttribs(t,{cellspacing:n.cellspacing,cellpadding:n.cellpadding,border:n.border}),r.dom.setStyles(t,{width:a(n.width),height:a(n.height)}),i=e.select("caption",t)[0],i&&!n.caption&&e.remove(i),!i&&n.caption&&(i=e.create("caption"),i.innerHTML=o.ie?"\xa0":'
    ',t.insertBefore(i,t.firstChild)),s(t),n.align&&r.formatter.apply("align"+n.align,{},t),r.focus(),r.addVisual()})}})}function d(e,t){r.windowManager.open({title:"Merge cells",body:[{label:"Cols",name:"cols",type:"textbox",size:10},{label:"Rows",name:"rows",type:"textbox",size:10}],onsubmit:function(){var n=this.toJSON();r.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})}function u(){var e=r.dom,t,n,o=[];o=r.dom.select("td.mce-item-selected,th.mce-item-selected"),t=r.dom.getParent(r.selection.getStart(),"td,th"),!o.length&&t&&o.push(t),t=t||o[0],n={width:i(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:i(e.getStyle(t,"height")||e.getAttrib(t,"height")),scope:e.getAttrib(t,"scope")},n.type=t.nodeName.toLowerCase(),l("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Cell properties",items:{type:"form",data:n,layout:"grid",columns:2,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var t=this.toJSON();r.undoManager.transact(function(){l(o,function(n){r.dom.setAttrib(n,"scope",t.scope),r.dom.setStyles(n,{width:a(t.width),height:a(t.height)}),t.type&&n.nodeName.toLowerCase()!=t.type&&(n=e.rename(n,t.type)),s(n),t.align&&r.formatter.apply("align"+t.align,{},n)}),r.focus()})}})}function f(){var e=r.dom,t,n,o,c,d=[];t=r.dom.getParent(r.selection.getStart(),"table"),n=r.dom.getParent(r.selection.getStart(),"td,th"),l(t.rows,function(t){l(t.cells,function(r){return e.hasClass(r,"mce-item-selected")||r==n?(d.push(t),!1):void 0})}),o=d[0],c={height:i(e.getStyle(o,"height")||e.getAttrib(o,"height")),scope:e.getAttrib(o,"scope")},c.type=o.parentNode.nodeName.toLowerCase(),l("left center right".split(" "),function(e){r.formatter.matchNode(o,"align"+e)&&(c.align=e)}),r.windowManager.open({title:"Row properties",items:{type:"form",data:c,columns:2,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,menu:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,menu:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"}]},onsubmit:function(){var t=this.toJSON(),n,i,o;r.undoManager.transact(function(){var c=t.type;l(d,function(l){r.dom.setAttrib(l,"scope",t.scope),r.dom.setStyles(l,{height:a(t.height)}),c!=l.parentNode.nodeName.toLowerCase()&&(n=e.getParent(l,"table"),i=l.parentNode,o=e.select(c,n)[0],o||(o=e.create(c),n.firstChild?n.insertBefore(o,n.firstChild):n.appendChild(o)),o.appendChild(l),i.hasChildNodes()||e.remove(i)),s(l),t.align&&r.formatter.apply("align"+t.align,{},l)}),r.focus()})}})}function p(e){return function(){r.execCommand(e)}}function m(e,t){var n,i,a;for(a="",n=0;t>n;n++){for(a+="",i=0;e>i;i++)a+="";a+=""}a+="
    "+(o.ie?" ":"
    ")+"
    ",r.insertContent(a)}function h(e,t){function n(){e.disabled(!r.dom.getParent(r.selection.getStart(),t)),r.selection.selectorChanged(t,function(t){e.disabled(!t)})}r.initialized?n():r.on("init",n)}function g(){h(this,"table")}function v(){h(this,"td,th")}function y(){var e="";e='';for(var t=0;10>t;t++){e+="";for(var n=0;10>n;n++)e+='';e+=""}return e+="",e+='

    0 x 0
    '}var b,C,x=this;r.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onhide:function(){r.dom.removeClass(this.menu.items()[0].getEl().getElementsByTagName("a"),"mce-active")},menu:[{type:"container",html:y(),onmousemove:function(e){var t,n,i=e.target;if("A"==i.nodeName){var o=r.dom.getParent(i,"table"),a=i.getAttribute("data-mce-index"),s=e.control.parent().rel;if(a!=this.lastPos){if(a=a.split(","),a[0]=parseInt(a[0],10),a[1]=parseInt(a[1],10),e.control.isRtl()||"tl-tr"==s){for(n=9;n>=0;n--)for(t=0;10>t;t++)r.dom.toggleClass(o.rows[n].childNodes[t].firstChild,"mce-active",t>=a[0]&&n<=a[1]);a[0]=9-a[0],o.nextSibling.innerHTML=a[0]+" x "+(a[1]+1)}else{for(n=0;10>n;n++)for(t=0;10>t;t++)r.dom.toggleClass(o.rows[n].childNodes[t].firstChild,"mce-active",t<=a[0]&&n<=a[1]);o.nextSibling.innerHTML=a[0]+1+" x "+(a[1]+1)}this.lastPos=a}}},onclick:function(e){"A"==e.target.nodeName&&this.lastPos&&(e.preventDefault(),m(this.lastPos[0]+1,this.lastPos[1]+1),this.parent().cancel())}}]}),r.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:g,onclick:c}),r.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:g,cmd:"mceTableDelete"}),r.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:p("mceTableCellProps"),onPostRender:v},{text:"Merge cells",onclick:p("mceTableMergeCells"),onPostRender:v},{text:"Split cell",onclick:p("mceTableSplitCells"),onPostRender:v}]}),r.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:p("mceTableInsertRowBefore"),onPostRender:v},{text:"Insert row after",onclick:p("mceTableInsertRowAfter"),onPostRender:v},{text:"Delete row",onclick:p("mceTableDeleteRow"),onPostRender:v},{text:"Row properties",onclick:p("mceTableRowProps"),onPostRender:v},{text:"-"},{text:"Cut row",onclick:p("mceTableCutRow"),onPostRender:v},{text:"Copy row",onclick:p("mceTableCopyRow"),onPostRender:v},{text:"Paste row before",onclick:p("mceTablePasteRowBefore"),onPostRender:v},{text:"Paste row after",onclick:p("mceTablePasteRowAfter"),onPostRender:v}]}),r.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:p("mceTableInsertColBefore"),onPostRender:v},{text:"Insert column after",onclick:p("mceTableInsertColAfter"),onPostRender:v},{text:"Delete column",onclick:p("mceTableDeleteCol"),onPostRender:v}]});var w=[];l("inserttable tableprops deletetable | cell row column".split(" "),function(e){"|"==e?w.push({text:"-"}):w.push(r.menuItems[e])}),r.addButton("table",{type:"menubutton",title:"Table",menu:w}),o.isIE||r.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(r.selection.select(e),r.nodeChanged())}),x.quirks=new t(r),r.on("Init",function(){b=r.windowManager,x.cellSelection=new n(r)}),l({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t,n,i;i=r.dom.getParent(r.selection.getStart(),"th,td"),i&&(t=i.rowSpan,n=i.colSpan),r.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():d(e,i)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){C=e.cutRows()},mceTableCopyRow:function(e){C=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(C,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(C)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){r.addCommand(n,function(){var n=new e(r);n&&(t(n),r.execCommand("mceRepaint"),x.cellSelection.clear())})}),l({mceInsertTable:function(){c()},mceTableRowProps:f,mceTableCellProps:u},function(e,t){r.addCommand(t,function(t,n){e(n)})})}var l=r.each;a.add("table",s)}),a([l,u,p,h])}(this); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/template/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/template/plugin.min.js new file mode 100644 index 0000000..91a8b5f --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(e){function t(t){return function(){var a=e.settings.templates;"string"==typeof a?tinymce.util.XHR.send({url:a,success:function(e){t(tinymce.util.JSON.parse(e))}}):t(a)}}function a(t){function a(t){function a(t){if(-1==t.indexOf("")){var a="";tinymce.each(e.contentCSS,function(t){a+=''}),t=""+a+""+""+t+""+""}t=r(t,"template_preview_replace_values");var l=n.find("iframe")[0].getEl().contentWindow.document;l.open(),l.write(t),l.close()}var c=t.control.value();c.url?tinymce.util.XHR.send({url:c.url,success:function(e){l=e,a(l)}}):(l=c.content,a(l)),n.find("#description")[0].text(t.control.value().description)}var n,l,i=[];return t&&0!==t.length?(tinymce.each(t,function(e){i.push({selected:!i.length,text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),n=e.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:i,onselect:a}}]},{type:"label",name:"description",label:"Description",text:" "},{type:"iframe",flex:1,border:1}],onsubmit:function(){c(!1,l)},width:e.getParam("template_popup_width",600),height:e.getParam("template_popup_height",500)}),n.find("listbox")[0].fire("select"),void 0):(e.windowManager.alert("No templates defined"),void 0)}function n(t,a){function n(e,t){if(e=""+e,e.length0&&(o=p.create("div",null),o.appendChild(s[0].cloneNode(!0))),i(p.select("*",o),function(t){c(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),c(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),c(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=m)}),l(o),e.execCommand("mceInsertContent",!1,o.innerHTML),e.addVisual()}var i=tinymce.each;e.addCommand("mceInsertTemplate",c),e.addButton("template",{title:"Insert template",onclick:t(a)}),e.addMenuItem("template",{text:"Insert template",onclick:t(a),context:"insert"}),e.on("PreProcess",function(t){var a=e.dom;i(a.select("div",t.node),function(t){a.hasClass(t,"mceTmpl")&&(i(a.select("*",t),function(t){a.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),l(t))})})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/textcolor/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 0000000..ee943e4 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(e){function o(){var o,t,r=[];for(t=e.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Brown","C0C0C0","Silver","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum","FFFFFF","White"],o=0;o',c=t.length-1,n=e.settings.textcolor_rows||5,a=e.settings.textcolor_cols||8,i=0;n>i;i++){for(l+="",F=0;a>F;F++)d=i*a+F,d>c?l+="":(r=t[d],l+='
    '+"
    "+"");l+=""}return l+=""}function r(o){var t,r=this.parent();(t=o.target.getAttribute("data-mce-color"))&&(r.hidePanel(),t="#"+t,r.color(t),e.execCommand(r.settings.selectcmd,!1,t))}function l(){var o=this;o._color&&e.execCommand(o.settings.selectcmd,!1,o._color)}e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",selectcmd:"ForeColor",panel:{html:t,onclick:r},onclick:l}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",selectcmd:"HiliteColor",panel:{html:t,onclick:r},onclick:l})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/css/visualblocks.css b/plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/css/visualblocks.css new file mode 100644 index 0000000..fe6fa93 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/css/visualblocks.css @@ -0,0 +1,128 @@ +.mce-visualblocks p { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7); +} + +.mce-visualblocks h1 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==); +} + +.mce-visualblocks h2 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==); +} + +.mce-visualblocks h3 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7); +} + +.mce-visualblocks h4 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==); +} + +.mce-visualblocks h5 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==); +} + +.mce-visualblocks h6 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==); +} + +.mce-visualblocks div { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7); +} + +.mce-visualblocks section { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=); +} + +.mce-visualblocks article { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7); +} + +.mce-visualblocks blockquote { + padding-top: 10px; + border: 1px dashed #BBB; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7); +} + +.mce-visualblocks address { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=); +} + +.mce-visualblocks pre { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==); +} + +.mce-visualblocks figure { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7); +} + +.mce-visualblocks hgroup { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7); +} + +.mce-visualblocks aside { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=); +} + +.mce-visualblocks figcaption { + border: 1px dashed #BBB; +} + +.mce-visualblocks ul { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==) +} + +.mce-visualblocks ol { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==); +} diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/plugin.min.js new file mode 100644 index 0000000..cafa418 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/visualblocks/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualblocks",function(e,t){function n(){var t=this;t.active(r),e.on("VisualBlocks",function(){t.active(e.dom.hasClass(e.getBody(),"mce-visualblocks"))})}var i,a,r;window.NodeList&&(e.addCommand("mceVisualBlocks",function(){var n,o=e.dom;i||(i=o.uniqueId(),n=o.create("link",{id:i,rel:"stylesheet",href:t+"/css/visualblocks.css"}),e.getDoc().getElementsByTagName("head")[0].appendChild(n)),e.on("PreviewFormats AfterPreviewFormats",function(t){r&&o.toggleClass(e.getBody(),"mce-visualblocks","afterpreviewformats"==t.type)}),o.toggleClass(e.getBody(),"mce-visualblocks"),r=e.dom.hasClass(e.getBody(),"mce-visualblocks"),a&&a.active(o.hasClass(e.getBody(),"mce-visualblocks")),e.fire("VisualBlocks")}),e.addButton("visualblocks",{title:"Show blocks",cmd:"mceVisualBlocks",onPostRender:n}),e.addMenuItem("visualblocks",{text:"Show blocks",cmd:"mceVisualBlocks",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("init",function(){e.settings.visualblocks_default_state&&e.execCommand("mceVisualBlocks",!1,null,{skip_focus:!0})}),e.on("remove",function(){e.dom.removeClass(e.getBody(),"mce-visualblocks")}))}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/visualchars/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/visualchars/plugin.min.js new file mode 100644 index 0000000..4474238 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/visualchars/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualchars",function(e){function t(t){var n,a,r,o,l,s,c=e.getBody(),d=e.selection;if(i=!i,e.fire("VisualChars",{state:i}),t&&(s=d.getBookmark()),i)for(a=[],tinymce.walk(c,function(e){3==e.nodeType&&e.nodeValue&&-1!=e.nodeValue.indexOf(" ")&&a.push(e)},"childNodes"),r=0;r$1'),l=e.dom.create("div",null,o);n=l.lastChild;)e.dom.insertAfter(n,a[r]);e.dom.remove(a[r])}else for(a=e.dom.select("span.mce-nbsp",c),r=a.length-1;r>=0;r--)e.dom.remove(a[r],1);d.moveToBookmark(s)}function n(){var t=this;e.on("VisualChars",function(e){t.active(e.state)})}var i;e.addCommand("mceVisualChars",t),e.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n}),e.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("beforegetcontent",function(e){i&&"raw"!=e.format&&!e.draft&&(i=!0,t(!1))})}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/plugins/wordcount/plugin.min.js b/plugins/web_gui/static/plugins/tinymce/plugins/wordcount/plugin.min.js new file mode 100644 index 0000000..acda5d0 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(e){function t(){e.theme.panel.find("#wordcount").text(["Words: {0}",a.getCount()])}var n,o,a=this;n=e.getParam("wordcount_countregex",/[\w\u2019\x27\-\u0600-\u06FF]+/g),o=e.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),e.on("init",function(){var n=e.theme.panel&&e.theme.panel.find("#statusbar")[0];n&&window.setTimeout(function(){n.insert({type:"label",name:"wordcount",text:["Words: {0}",a.getCount()],classes:"wordcount",disabled:e.settings.readonly},0),e.on("setcontent beforeaddundo",t),e.on("keyup",function(e){32==e.keyCode&&t()})},0)}),a.getCount=function(){var t=e.getContent({format:"raw"}),a=0;if(t){t=t.replace(/\.\.\./g," "),t=t.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," "),t=t.replace(/(\w+)(&.+?;)+(\w+)/,"$1$3").replace(/&.+?;/g," "),t=t.replace(o,"");var r=t.match(n);r&&(a=r.length)}return a}}); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.inline.min.css b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.inline.min.css new file mode 100644 index 0000000..0592828 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.inline.min.css @@ -0,0 +1 @@ +.mce-object{border:1px dotted #3A3A3A;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.min.css b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.min.css new file mode 100644 index 0000000..eafd461 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/content.min.css @@ -0,0 +1 @@ +body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px}.mce-object{border:1px dotted #3A3A3A;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/readme.md b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/readme.md new file mode 100644 index 0000000..fa5d639 --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/readme.md @@ -0,0 +1 @@ +Icons are generated and provided by the http://icomoon.io service. diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.eot b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.eot new file mode 100644 index 0000000000000000000000000000000000000000..128a98f3d81337dbcab72a183ac19914b3e2c5fe GIT binary patch literal 8348 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 G-2V#}OT3@} literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.svg b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.svg new file mode 100644 index 0000000..fd5e3ff --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.svg @@ -0,0 +1,175 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.ttf b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7b50bfdae94f6efce635dcc26469ffb77c123a97 GIT binary patch literal 8164 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 literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.woff b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce-small.woff new file mode 100644 index 0000000000000000000000000000000000000000..725aaf19e21fef9e2510c6934bde9f52f042afe3 GIT binary patch literal 8340 zcmZX4Wl&sAwC&)7Lx4d-U~qSLclY2vxRW43hY;K?xVr=k?jC{;1b26b06`w#efQt( zs#RTUoz;7vv%9LRy8C#k$;zr}YpVeO;A8+g;H~k+1K|Ga|8J9$l?4L;a6kZnbQ1vJ zC?g>r2$Pl7RsjG$oV>Y7-arb8?&Ow}mXQSj$liQ_4{rbiECGmWT5Oze8vPqrdV?9; z%8Iz9lez1g=K03c-r|lH4yIY!TANz|0OS~N8v7e~U*5%b+rEi!n(!MZe*-ll;C08= z$a_`zF_-x@JjLar_zZ#lu? zZ`yx(zyJgQz&mTu;ET7`U{mfYgf2g>QCu@GIa$&NS<$YrASgL32vLI_MMGR2E+q*2 zL_>Jwy~H9A_y+-r09OVGw!lSX17E32$>iMwg0CvXYa7)U>e@ZeTuv2W1(z%TCZEsJ z&JDjn#xr;v=Bo4?=9H-+?Cc7O%&lr-*H`y+vdw|!PnO$591M{PCucnf8o|NS!QYT+ zSPde$7A!v&q8z))pb~B=CkY34h}UGj<6))rDhGcamMSUP0m?%dV0j9NV@*k z42Pj#{Xl8qeR$K@+LlM${SAJu$<~aNUt82<_STHTs}(wHx>xw*>DD%W?(%>fMkdX7 zYt%V?sEuyCO}vu&gjuFI1gRMGEQs71E?|Y~*6{UWv3C)TqW-JAzGNyhg_2zG3B9~v zWK(P}FGpdlMZkwpD}DHM;@NbfvO*$W!<*kAr^N}wu|3`Q7Rnh^owS{-<0<%dIXB<9 zO%1>-$!p0Vg{WfTLzY9Q!*$p@yYgf7)FGAK&zrhN zSpz1Y;!iMNyO5iRMvX`9C2D_K0{P71$zm3m?jgEeW@GlM>JVsfYvB_E%VUsv>L#JU zOiQo#>_@vJbKfQ5pA%PtdRtsu=P~5(U+teFzkZ5%mG`SV>+qeg)}L!t_>fpaGj2E4 zB=JegvVZ3rG3Go^l`1b?vjW+yxA!O&L*?mvSQAg?s_>6NDCoC=--^3hzi9UHxq0u8Sh{QF&>p81cbT{$uyyG2keW2?0W7t6jhyWPdTN1mYd zUlRfXhvy4YxISN~>@G-#3{&yMsfuaAk0N7k=iA2T=cADPCY%G~jP*(l5VAAa`4 zMV1{?OT_aj8%>l4DJ45kwp_2i-n6Hd7|>Puy0@is;k_l zBW9pTIvHVxh?fOdd`?ryLrPJN%lZ7LT#)K2c7Xqnb@YJHyKU`iasOXKt#d2YI8}5d z{gsa@1X=@Q=hPRGHL=35jR0dqNUl=J(n%gd@0GtdY$Wut@^O_V zRe@Z~RL~f?;q|>C^`aKlF-@ZENy1O3`K$~s%JXpFOXAo0r5Cl5QLp&&$5;Cb8_ANk z2WKvp8dBZNsfBN~y%Si(Oeyy7ndZbj+(i==+C{Fu(==zNe# zNc;WwTlIF=7o7F{&k37jiL;)66teEz?gkqM2cB6cUg?QL$Q)NPoCM3~WX{VzQFsx~ ztAYH|H>+1Im_=`;Ly2E|%(DK!kIz-UjXV6X8 zT@6>(4@T%1x=DM^DDnI5@awA;q5R$FFJzllr|C#pVLgPm0YKv1e2LEvXj?Uli^_n@3;p zHv_`KUu0PpS=NI7%rVO{O|3NT-QUAiu9R{2%Y9nL7nG0vEy3AIBVF>>4pi8N35JEs ze?rMB$iFLuuh`C)(S?VmB@5II&lS`J!(S#p!pmL_Xfu7(zXYV9HN`2m3AZ*Gu!zd?Ak;5wlIi;PZNma2%IAPE!{VxEGeQb zGlCC}3Q@J?9=#azH(z${IYDPY{mlb^e};GQQ09#5m8 z2HG^G$z@WJVT1N7Se7EXb;?5QEHtF5ojaH7_dx@|vKIAdkFV}upRJjj>;KfH}EM`L3D-xF$w+)%9KR=nVa@&y3aJ75Dpa zV-;Rv)JrmrSjwra3Y#+Nc0~usXSc4t`hk+R&hJ$j!z(B!Arv(BBMdOR?yVR7UP~9EGw&N{J!{ko%E{oD*ik3_vg(jX{}h^ zPLm4>)gcD!uQQK5SGEG$wT zE5doZ4jU-s-5rOpdz}fpUJ@FRv)Nn&J_Ica1rF%X!l+xm`A&*c4TjXkXw7SDls98p z*}L>Sw64dglb@WE@Aw~{TnOC76@hT`n?>k$_phtxB zCWCs~DZ!p(p?)L!V>!FjBMn*Wq}O%nh>Il%VWztHX_Nc?8Yp@a!`YL&eKov7q|z7G z@|w!ffe(^THw*#NmW^|RgC`49*aBkp=ail!FFd4_yEi?I== zNee*z-G5=du+;u(rHg@%tKXUn3x8m}LA&Vrvtnfa5!aC(bU@}|ig7O-Z=^oGpAzva zC+xI0#1n1D&*wCdn21wGq6<8H>V)pJFLNQSL-WSywmwZ9LjkX!CM@3bQL&R;$0-o0 znh_b~kcMgb+t`f2S_BlGN(&xd_F?=UtA?S6v&FW{lD*AXH;iy5WcC}y=IUhjWxc40 zS7vu(b5QsNLe~g+njLvs&^gwgFZqL%UQ|wipp?`29h?jX~*<) z-Y7eNY>rWj;e{n4$(R~3cbm7LhE9AFEob-z>vm!^Qxo`>E5B z05e4u%~Y0A2^5uAIYkO9J-qC<7`#EEHmmWkof7~1vO(Q?%=c#hJPSgsj1;CH$9LyvSv35T5oD2!P7hh*3KO}UxRNxd` zVA61`f9C5cN*%#?=9SL8y{@3x_t|0E<6Gmtw(oj|5=sme+?feE-CxHC>GhxLS`xB1 z`3P1dVi&VKYb5FwG=6ZtUE%y#t0Up3FS}@lx1UDTFIpcK1XQ7CKm;xO%%T=#VY=mf z$tnRh*%gxaHd|d!XKdGIRFO0H_-L zW*Q{qL>(#;*_n991+|~UPv`8O-p30UZ*{cmuED>=>b7sZ_vei>*x+fMMa#q<2JV~2 z^DPLV*o}9^>aWi|?pq5BYAhf& zlJ6UkSa4pgb#O#2tz8@v3))?3PXsxg%ZnRQW<}Ud%N7`YjcxZ;caetH(Fp=$ne+b; z;LujFa&2!&$`|eW#)6ZlB7GSn<;G?1XSF2aH9V#Bi`r&%cU%cs)#Ya)Ohc?fq2e9C zpjO6O@i+3nWXhb^;elG-9mM-#8-@30H%XsaM9g$Br}XtkjqBrO@~RmUK&6bm+a->C zRSzd&=N>Q1G4r*NY3RKUs^t9HxR{U2zLH!IDz%x86ZTcwv__3Fs)<%vB7z&mC`m}M zrdKkh7E#fn=+>simXCrH25{HKRTfb3(lFKy<6creK5eg7)aWEvxDPz7sU`u*a?}y{#Y2wA)0qTM?Q!I73y{oQI)i+IVPACk6?1 zAWl_)9sJ~rG;=>aY4&)T{wKR5@G3)j zw{S^GGj>72obmY=dDu{abi_1yGDvn@2tX5f@%(P$+b2g;( zdYsk2JZO*B)TPZfEva}Uouqyq0mhn*Q84H#Nm#!CND zGlWkQ0U3{A53eGq2eIO=*`xetc{Jy+I3;Jcc!9E;RZ02S-o>MeN%cs{fg3gN@7elm zU((jd9dBXg1QF_DGPyl&pEV*ZQn^q%Z$aT+0&qs^)I!l7P4MMyL%&6#ttTB}( zn%Te0Cn(IDwr-=js&M1x?G%vPUzY0ve+t6|@vy}Q>pYmOzl1%W_H`M@NIlOdvEh2x zeLlRh4^u6`@p1Uj1T`dg$NxwOz1y?ymv29a-F)y2|I7$W&s!}0^#6;de^D~c^%X7j$=o2s))MNAgJ zs$6;CRaacsd|Qc!iUs4XN`}kkif)MFQYC%92J#j;h*j~}+~$ZNsriz>yGeFZ*;vb! zQEug{6xl~v8V@mj23+3ht!rH{Y`_U_EMq!IB@d2lqQ|M9^KFWq3n-CJU;OLiCfU?! zt4I&^b2?Dp!DE#Xyw?Khpnp#j_S-DyDBB+A!0rAxSZ zC6#6;@*~%KBk{cU$xvvyL5Brp<@gB}H$+FROfL%D_ZUhSQ&q9TuUF|o$x z%eQAKV_0=pGJ3I%$mWK(rGW6%{vrX-+bUNUlV3Vz$60W&!oXTc>5$uHKeD)fg!A~F z+eZnfiuwYMjhenmB3EB0I0u3N+8;+432g~4N1fRUH+6_hNGnYWqsrsuy9``9bOaKG zBTI1f4(aton=(1|9~(5M%kz78(IW|ox4=E5b?HxJX&UcCg_rY62p#!XvKs==rK9-^ zsc2pehRg<*fxHjnzEd5CIUdO$o?d7ZM>2jYVgFeD@wr>0a?0H)Ag#Z!jf(Aj-AE0r z=+RUB=*LR0*i9R2ri#TgPu}`(D*oB-rx2n7=1+y*0W&FDM|Xi6Y-WHDa`BKTVetTK zk^y4#=~Uzs>o~D%zepU^EI*3!&(SSEDW_n<>-VF`t8vAQrDqHN zBw?ielfD3hoFe@xmRME0hXxP#GJ_2WdNP@n_47ke{N_O^OF3fmm*m7ls@0pf>|7uV*K^95FNUEkS?MDiqgNjRPe94h}&3G20=UvJ^AR#8JupM2d!RMsEVFK za(W~ysP$z+E}@0HWm3{sRy*8tX)RYduP$DlJN_&94B3S^@AQu#t=aA$CT6kamf2I~ zKrMbWTas9K*>8nGayLK-^fD0Wfp5}T`O71pU9LT-C$%T#SfD~eNi5dL4sklJiVOD$ z0&_qF6GV}S7oP*iXg0VUfb2h#o1u3}rP`G0+0Gd7og_n-O7xf4+JfXYvOS^ymZXyY z_UiN(m|@NtcJ=l4w%W?j)5%ayuPE5JNhyVKZB6sI`F($M^017^^$%B2|rn}=^S^UGVb8`Ym$7t-l zk!%_|8k}YWQLx&)(J!+AS1Dn3qUQp{pxGT1Q z6g#E)jl6oQrjcQ50gCr1zSqHYuCkjP_o|5ufvEU|6@JAH#JnKv7vnnLNXf4d6cUg| zzgX}7`{x{gH$W;Mzjc)|n<%pHWj^5`ug=XD9(=Gmg3jUU^(nseo`0aMysw{I(Anx^ zi0Lf{sgTB`rP{@c0=sjXTUC%EAweZcwR21pCwAhuZ8@$zr)=Xolq0I z5%G;{LATix*$>}-msOa=H9+6dQH6N4wCu%ocRm;v|DL-e)~Kr}06@Er`f$8>^)t`! zMCjw1#z5dNsuHkU%wni;DaQ0m@G3gP?2-temK}t3%(yD`K~(UAq0J!K(Pe^(->(pfpoumxs+KisDI#$->~kkyd)z$+=`30GMhGqmJtQpHukqd8^lP;1q1-Rq zvduZAZuzwEk1=i#$4cyuPWBkte;k^UPtO-A9;5sXdvW4D9e8c_EuwJKJOb0-jyKZS zl$DEgPu3EJlFGu6TK8%{El>=Ks2>Hd5{e+jzQ#3asVkmBV`L(HWJngDth4a+)U>B` z9ER9Fww=?*2r8n^Ym6dv7g8S!wUvt5^TYjBnSX5lRqp9R5LiZV%O)MMM!b9GneMAu z=yt&I*r*XbURlyjyR)fNE<|BTS43{D_XDl9HSk7010C`CRKhoO5%u+IIj_=U!q%VM zcfl*c*KbsR31pR@MlMd0rK&K7+3!AKfcP#2N16PJN*Ga7QhfrUK`n9|#JYMthrxKGc^McjSzTdE@`f>J2isjaw7gqdCtkhG6y$%=n!?ZHN)WQ+uNuVc; zK+=LS1gi{x*nMPg(M5UB1o1Vr`vW}-EP&;yvRu01U=v|@+47^NbXk**KRhb6vj=p$ z)N{ag5m2yTtE)^m;ad6{F(2I6iP2q8H12c9-pK?S=aVD>)$pGbA*h`Is(LBpReNEe zZcS^*^(Pmzy59%7_LqqKpSl8+qM;4r6(k35>(fI55tR5BQO1W}GUcMTPZBl?F!7n+?UUf91YIuC|2v;jY)xb}kzWo@7`2IgZFMS8Rr`U;vW z8VkRSn&}SI&$C=js$R9h5UBr=FR+oB+UnA4tdycIpIP9`Ek#|rwIDMeOr)?J`nFkn zS&aEMAemmXKf=A^S5Q9_Un{5NMTM!aymG)_NWmeCk10S4Y)inq@t2h&3lD!X=Aiz_ ze@hW@`WNCqvSCJ~i~C8liTT@XN;NiW-98dsQ2F-|sUy4-=~s`XSN8zdNA<7F-|&wT zest0&t4JMWxkt#-Q4 zZxm;`aPU;Pef=xVxF)CaT6$h6W00USUL2;r6XN`K=Apu=dgY5hco|&aEyxr}Xxc58 zzLQ?WgeiFCo$#scCT>49uHQ?EB_c1t?N$$FX#0Z3608BVOY^B%iA<{zO!cYVsw8dT zX&a2qxMkXkbz^rw4ESz5mS$TtHsS0c#v=tCT|--hcwPDT#7s*OvR*>FpA~nsQIoOEGHtgAzN=FWNMd z3yaHMR<)hu!Scg_4*Zi*S#T~e#3TP3Nfuau@FW#2%wEUwd|U20^1isqYi4`lw*tMOuZBNgL|O>HlfM^UvWI`44!ku! zL891%vJ^wc3l7289?pjic1mAl*^43E$nN#w&q?(BDuw&QjqZrVFd(zVZDczB5BYE- zXWj0vFe0m3(nZE3cL+U&{KujAYACD>fq4V$&KC0dbIB__Z4C@geitLlNJkHcKyKd2 zu50)11#+u<6xFi32eTY-Asbp3kU^E`vv8!-aHhh^OHYEUp2rMtfiIe>JjwsbZ59#B z9kvf$dA5?Yg#Yz8dxM;w%%3u=q-7^s%0f_j{3!z|n~ow5yjTYdqfou&7#WNt%SEMwX+F8(d5C_bH1E8Q61BW?`GhTEb7GLB%v zEe;)V(GVx83+PCNw|z+pt&yrA2WdVRraTt7nv-83tmPxjvyb#32eK=_Fo$rLg5y5m+X1{~D<*i*EzAC%alOChB_?LW4GXR7m zxL|VXpg#-Ap!o7cZ|~kr87mgU-gZQ+EAv>fpAG`O_GBLdA3Ty3F(21+oViEUPR(Y! z;h*=#u%3%*@OR08Pq%_y&G7+IE*E!UTw)BW?Zv zXI5rr8weJt$T(&eW{8qnUVEeygAr@v?Jw2m6y$Ai@hkAN8u!_4mL4MC9!B+;5IP0(t-i6#z#PgZ%A1c4H%O zq3RgY>x42Lmt7ZKI4)ly%)O(`1Cjx#pMxICbXvI5t+?7V0ifI~bt2)=@?;wydA9BN z1me?U^bQe>G~I|hg+3tJ8Q zJqZ++v|o*ODu$DB9eA1b-3sK=u$&-c`s!4aduXG3|DImAF#r1C>-iOpPyLg2QA;ar`a}a$G zGD6nw!2o2MBJKVc&msswi;Rr)4H>L!b^&2WnL)$A5(kjViUK*zyD5@#AnOtht0ko8 L?FR&Z0OJ1xJUq%= literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.eot b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.eot new file mode 100644 index 0000000000000000000000000000000000000000..b769c2c6611cc18f5cc9ec35528d9924f3a5541e GIT binary patch literal 8276 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 QJ?PKAbfGBe`tQ~M1DmY + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.ttf b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/fonts/tinymce.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a31b584c2bc361084bfd1745ccaee5b70181e4ed GIT binary patch literal 8112 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


    geWSell!|GRp<_hLGWxI@5bh$gS##zwF$Wj> zT`njhmGfLBJ+1Z!;Xs~(UebC{QVjE}UlutJ3`{Mn3MwAU zb8W1%8W4delcA8?Mim+V}smbf^0vdWtifqduifdt>{t zHo%c>!kR1)?*VOpW5aDZ_7Am+C(844SJik8!#m&}yn8d<@b{Am(N`YC&KrJ@-!Wpd zHU^1aO;IFwe985bJb$!*2*Hj@ivWQi(BFrm)i

    ^0jpb9P<1G1GFXVz|iN5e_&@f zat$p^V4BKRbNy#A8ZK_FOa6Y>-sUU4Wn%y7%FJ8SyLQQB7bEs=>LVV3G zhov)?>sI_qG7cKHp!`F;^u^f6^@=8}&~Mj{*0)2!*26Wx4d+*3H-3a$7_RUHS6{Ph z`C#t!KdPvswye$X@A>by0-=V2@$r^CXAcC3S9;u;##EN>EEI+uN&(3=FNOE{HQkZi zc^8wBwdBi8rQfjTyufE`Sa52@Go@lD3dmODwxY$9U9vQVpOch01(7rfCR?WY)p$ld zBhnRRPq?Vcp7%?``5ZqivFm`p>@AX2M{jVzB$a)RhYy;yS$qS%S#yg#436o%>QsJE9lXk@hdu92i3CzxVjy##S;ESx@g?Kxs z3o#y7?cXoJ1vgZ`Eh;GlB-7?5)s=oq*9Ca5>x z!)tFwgNb(TH!Ds(O{_+SXz6k5NPWqZK@KbPpcH3K_)7Ay10Ip!Nyi^;Y#eWr z-H%u1Ig=-q$l(dzddvi3VL}E(eM=(!qhUt2xQ>P7*|kC7Wiqe0+8~V__#(ez>7#7c z#>}@~R1x(rN(i6%U9D;`zOkosXtXUZi)-X6T1J?Bp^!4-E8D&Mb}*!<8J5KKr`+vv zt|0eMFTD2;Z*d%cN?uVN1i4ap>`kocTdiNmYlJP+Dze1k#mdvP0y!Izp$qTw;hBnh z@?h5h>9m)G&}!InP`pBz9TnDa%Zi*AYsuwWh#X2!d37Z`;<7kCdsyg3b{c`R!rrnK zJD9T5`&_6y`?{d83!1$RCFR2mCzaBTz=Bk+K z3jmIxQQzoQd==d-w=dWlGyB0&xh)%2=>OcLCg=yFfX_1_{Xpp~oQ z*qNn3F&`&0u5o0d<%9pi^AARL!)Q;gUmZ>#!vv8--_Z6&(XV|wW`EM+@SCafj_NvC z4$5O7&&G}Nv+iOK;i^Rly+@po{3g#77>V+848<*!&f}QBB=mH3M#YZ zEUt5wd6z^XbFEUCss3slB(c~~tl163M_l~plWgX{{P_6wUatpyi zosztl@}x#S4dc$RXY`7tEbz0id_}9bE=GN-9+9dnM!SHdvrc{*92VY!+gV?iB1pi4 z@2Q+9K`$2XytOnR@?qFm-flZ;yETq9KX!*cgn=wei1zreliY`vyE_unslFzyQ@CKWcD{m+N<0seiV|8 z35gmjTcqG_83l{|E6X>`2T!rgHoFFxO~+N2HP7kmYOM+U<&xcGFUm z#aMHH`~E91+t%Yeqv{v!DF*gMzO9ktvhslP-4ETlxS+&C$)yz0srb15&cFYq)c)|6 z>cB4P70Q%Zj0qAvrjdyethg)C0_uhk0AB>K`9IfMm>6Yr zb`E!T9rmR3cXn=~gFDz|*=t!@S=lPtIXZ&?!9$qw`)S>qmw{U_Fgqb17=*Wk2X20H!!9Ibt7Gs;FHWT`;B3_5r-$(;I5w-GtYhl z!W&-*DOwAn=j5`|h%_nmT0=05t%yYSiG0)Rv!Qq@^m$#k2ZMwJ>g{xDOooE_I0_#X z2sum!MahJk-K=KvA&n0ww z__&<)9*QNOfO&7g+h&E+}5;RT%u?*QUe_JA39lXf=a#EbqU?V4qYYHf z+Kj~->h8(fqBpI}yt4hlShTij9db{St|+DVt=D@O$xnFTLcXNtkC!*=Ah@tR?J`^# zWt-W$o|2Q3!; Q|9KxRIw6}F`~k543putNr2qf` literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/anchor.gif b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/anchor.gif new file mode 100644 index 0000000000000000000000000000000000000000..606348c7f53dba169a9aca7279a2a973f4b07bdb GIT binary patch literal 53 zcmZ?wbhEHbWM^P!XkcUjg8%>jEB<5wG8q|kKzxu40~1eAV&{y5e`l1KFoiKNSOWkz C+YCGa literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/loader.gif b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..c69e937232b24ea30f01c68bbd2ebc798dcecfcb GIT binary patch literal 2608 zcmdVcdr(tX9tZGC9yiG~=H_*Q-0%n(kWqP*D#hw{AQu8;1%gl-Hrf&{2?48KX;hHy z3Ze*zEz4t3XdUFyLbNPUYlA`|B}P=N1fqtL1*}S;87#|-W9v<#G;ul(e%d3)N(^9c$d2Dz{7}?ErjNd;{EMKkCsk21~b9Gvg zDo<7L=3Z5HNbVlZUcm1eg#o#CZCJU`3IYHwM->zCd?uYrF3vKFeM}v?f+%s?E>ly|3W25ry9#NNbTx-}0ON58dTrs^ix{_1O0Wh~SVSBlH)Ajn zPn^Gbjz}PCtN@#keR&hK&Dhl-b$kZ8^S)x#dh0{7X=X%CCJk7P1PSO>T&S8I4{#Lg zb5#)o=;!ZP*1nM{cI4@(x7o27*SA()NHmrn67aN@Pmi~(i_SnrjYnwh36aG%!@i0d zqbvfa44f|?OG4ntP|nbjhEl1)Yp6ZN@yjy zy4==QmLy%t;ps3R?~f2KfTTI|2?q8dFd6^z5GF+Xa&Y)sjG)hxit80pPcOP zJ z*LW{SyGHD%hUotV+W%I}fBLAIx!8|7#}$;clKQ+{&FjDqGQ2ZNx(lYM3*%~}ILnao zM`aui55~ZFJlu^!5rdA9Q_7H68H_;##u{x(Yn-vSfIRCb^Nqsg zGRS!Egm>h+o<}LeV4&CLReo9FrDjDvs}8?JwC)#Qs|ie=r?~xUh)&*d`Fx>FG}%X# zNdtDHBKhLPC0wpooFDAQKL%*6T|ULH$=wX!NhcasgD3d;-d$I6yRK3yN+E~C1335_iLOt+*9uvSZ`>*KA}vm}08wRq=>5l|t*Na&jR z-C1&C`nkEk#sB|@yyt-#fXngP04My zm7u$Q%EJbHp`>~`5W&L{W!6`y&}LMS;jfUpgO~7TLVMRZ9IC)IZp0A${`yp0{&wco z#1nx@XMkhqeK%7?RE7JdLr1^nwFfaJ0Q&Lv?WNJ%9}VSJsNY2+UYs2%EU0J~ayFXv zi*?7KCXQHkD)O6!0Q%4N+HTODHxJ{kQSuQX$l-rSwkwh(zMkdfzxyGwl@yHC)C4p< z&n2%8#M?)Q@mgHL1ot8`SFdSEj9ye|jHy+U8#@HoUExG=@AVkRAe_qYm4EpzK6L*& zh`)26?V#f4#_h^P9G^%>h2-H3)$QP zQovu6J9qDvsxqweDdNNa!Lb?L4_UF{tLX_nN7r0U_vF14YKcGR-*Gl} zx3oG)bzf|65dBxD-;2ZCp??K;+TuQ9onnK?==5hzbkb^r_g>z4#D8mcv8(+XdoszA zCx-qhdgxMNMotj}SiL_6V(tLcsK7(M(r(%u<}QrVfOvyK6_;~NOTlPGfX@M7S5YQF z&*$(ylJMHJt^_aQeu{C6NaTE$G3HNN@_SnN8YcaKn%`)F@~L1x+ah7-gEJPpc6w%3 zyX}r+Qk$4RHZzfH){e~F*qJ{d*L8a6n4;U?+{de0-t)mal#TVxe)3F}^UBh+zd T)6_**#cgp_+?JL9(ew3BlNF>u literal 0 HcmV?d00001 diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/object.gif b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/img/object.gif new file mode 100644 index 0000000000000000000000000000000000000000..cccd7f023fb80908cb33bb7d9604236cd21b7ae7 GIT binary patch literal 152 zcmV;J0B8S4Nk%w1VG#fg0J9GO<>lo+KR<78Z?v?uS65g4{r%Y3*xlXT%F4>`@9+2b z_ww@cot>Tk|Nk>HGXMYpA^8LW000jFEC2ui01*HU000C<(8)=wd#<&tyXIMjHBV`d zBSi|xsj3(;nD0kQ0aJq8eLH~x02P|t2!_J&Wqb%0io?#xD.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#9e9e9e;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#fff;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#fff;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#fff;border-top:1px solid #c5c5c5;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window.mce-fullscreen,.mce-window.mce-fullscreen .mce-foot{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:#fff;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-tooltip-inner{-webkit-box-shadow:0 0 5px #000000;-moz-box-shadow:0 0 5px #000000;box-shadow:0 0 5px #000000}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0px;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-btn{border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;background-image:-moz-linear-gradient(top, #f2f2f2, #ccc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#ccc));background-image:-webkit-linear-gradient(top, #f2f2f2, #ccc);background-image:-o-linear-gradient(top, #f2f2f2, #ccc);background-image:linear-gradient(to bottom, #f2f2f2, #ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffcccccc', GradientType=0);zoom:1}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn:not(.mce-disabled):active{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn button{padding:4px 10px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px #fff}.mce-primary{min-width:50px;color:#fff;border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #08c, #04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);zoom:1}.mce-primary:hover,.mce-primary:focus{background-color:#005fb3;background-image:-moz-linear-gradient(top, #0077b3, #003cb3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0077b3), to(#003cb3));background-image:-webkit-linear-gradient(top, #0077b3, #003cb3);background-image:-o-linear-gradient(top, #0077b3, #003cb3);background-image:linear-gradient(to bottom, #0077b3, #003cb3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0077b3', endColorstr='#ff003cb3', GradientType=0);zoom:1}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#005299;background-image:-moz-linear-gradient(top, #069, #039);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#069), to(#039));background-image:-webkit-linear-gradient(top, #069, #039);background-image:-o-linear-gradient(top, #069, #039);background-image:linear-gradient(to bottom, #069, #039);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff006699', endColorstr='#ff003399', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px #333}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px 0 1px 0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-btn-group .mce-first{border-left:1px solid #b1b1b1;border-left:1px solid rgba(0,0,0,0.25);-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.mce-btn-group .mce-last{border-right:1px solid #b1b1b1;border-right:1px solid rgba(0,0,0,0.1);-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.mce-btn-group .mce-first.mce-last{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-14px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;border-left:1px solid transparent;border-right:1px solid transparent}.mce-colorbutton:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:4px;margin-right:-14px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;margin-right:-17px;padding-left:0}.mce-rtl .mce-colorbutton button{padding-right:10px;padding-left:10px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px}.mce-combobox{display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox.mce-has-open input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.mce-combobox .mce-btn{border-left:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid #9e9e9e;width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);border:0;overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar{border:1px solid #c4c4c4}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:transparent;background:#e6e6e6;filter:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-menubtn.mce-disabled span{color:#aaa}.mce-menubtn span{color:#333;margin-right:2px;line-height:20px;*line-height:16px}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text{color:#fff}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:#fff}.mce-menu-item.mce-disabled:hover{background:#ccc}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:#fff}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:#fff}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#c8def4}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:#333}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:#fff}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);zoom:1}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:#cbcbcb;border-bottom:1px solid #fff;cursor:default;filter:none}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:#fff}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:2px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent;border-right:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-splitbtn button{padding-right:4px}.mce-splitbtn .mce-open{padding-left:4px}.mce-splitbtn .mce-open.mce-active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:10px;padding-left:10px}.mce-rtl .mce-splitbtn .mce-open{padding-left:4px;padding-right:4px}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#e3e3e3;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce';font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333;-ie7-icon:' '}.mce-btn-small .mce-ico{font-family:'tinymce-small'}.mce-ico,i.mce-i-checkbox{zoom:expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = this.currentStyle['-ie7-icon'].substr(1, 1) + ' ')}.mce-i-save{-ie7-icon:"\e000"}.mce-i-newdocument{-ie7-icon:"\e001"}.mce-i-fullpage{-ie7-icon:"\e002"}.mce-i-alignleft{-ie7-icon:"\e003"}.mce-i-aligncenter{-ie7-icon:"\e004"}.mce-i-alignright{-ie7-icon:"\e005"}.mce-i-alignjustify{-ie7-icon:"\e006"}.mce-i-cut{-ie7-icon:"\e007"}.mce-i-paste{-ie7-icon:"\e008"}.mce-i-searchreplace{-ie7-icon:"\e009"}.mce-i-bullist{-ie7-icon:"\e00a"}.mce-i-numlist{-ie7-icon:"\e00b"}.mce-i-indent{-ie7-icon:"\e00c"}.mce-i-outdent{-ie7-icon:"\e00d"}.mce-i-blockquote{-ie7-icon:"\e00e"}.mce-i-undo{-ie7-icon:"\e00f"}.mce-i-redo{-ie7-icon:"\e010"}.mce-i-link{-ie7-icon:"\e011"}.mce-i-unlink{-ie7-icon:"\e012"}.mce-i-anchor{-ie7-icon:"\e013"}.mce-i-image{-ie7-icon:"\e014"}.mce-i-media{-ie7-icon:"\e015"}.mce-i-help{-ie7-icon:"\e016"}.mce-i-code{-ie7-icon:"\e017"}.mce-i-inserttime{-ie7-icon:"\e018"}.mce-i-preview{-ie7-icon:"\e019"}.mce-i-forecolor{-ie7-icon:"\e01a"}.mce-i-backcolor{-ie7-icon:"\e01a"}.mce-i-table{-ie7-icon:"\e01b"}.mce-i-hr{-ie7-icon:"\e01c"}.mce-i-removeformat{-ie7-icon:"\e01d"}.mce-i-subscript{-ie7-icon:"\e01e"}.mce-i-superscript{-ie7-icon:"\e01f"}.mce-i-charmap{-ie7-icon:"\e020"}.mce-i-emoticons{-ie7-icon:"\e021"}.mce-i-print{-ie7-icon:"\e022"}.mce-i-fullscreen{-ie7-icon:"\e023"}.mce-i-spellchecker{-ie7-icon:"\e024"}.mce-i-nonbreaking{-ie7-icon:"\e025"}.mce-i-template{-ie7-icon:"\e026"}.mce-i-pagebreak{-ie7-icon:"\e027"}.mce-i-restoredraft{-ie7-icon:"\e028"}.mce-i-untitled{-ie7-icon:"\e029"}.mce-i-bold{-ie7-icon:"\e02a"}.mce-i-italic{-ie7-icon:"\e02b"}.mce-i-underline{-ie7-icon:"\e02c"}.mce-i-strikethrough{-ie7-icon:"\e02d"}.mce-i-visualchars{-ie7-icon:"\e02e"}.mce-i-ltr{-ie7-icon:"\e02f"}.mce-i-rtl{-ie7-icon:"\e030"}.mce-i-copy{-ie7-icon:"\e031"}.mce-i-resize{-ie7-icon:"\e032"}.mce-i-browse{-ie7-icon:"\e034"}.mce-i-pastetext{-ie7-icon:"\e035"}.mce-i-checkbox,.mce-i-selected{-ie7-icon:"\e033"}.mce-i-selected{visibility:hidden}.mce-i-backcolor{background:#BBB} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/skins/lightgray/skin.min.css b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/skin.min.css new file mode 100644 index 0000000..86c4eac --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/skins/lightgray/skin.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:visible !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid #9e9e9e;width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td div{border:1px solid #d6d6d6;width:12px;height:12px;margin:2px;cursor:pointer}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover{border-color:#a1a1a1}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#a1a1a1;background:#c8def4}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-toolbar-grp{padding-bottom:2px}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scroll{position:relative}.mce-panel{border:0 solid #9e9e9e;background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fdfdfd, #ddd);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdfdfd), to(#ddd));background-image:-webkit-linear-gradient(top, #fdfdfd, #ddd);background-image:-o-linear-gradient(top, #fdfdfd, #ddd);background-image:linear-gradient(to bottom, #fdfdfd, #ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd', endColorstr='#ffdddddd', GradientType=0);zoom:1}.mce-floatpanel{position:absolute;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2)}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);top:0;left:0;background:#fff;border:1px solid #9e9e9e;border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#9e9e9e;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#fff;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#fff;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#fff;border-top:1px solid #c5c5c5;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window.mce-fullscreen,.mce-window.mce-fullscreen .mce-foot{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:#fff;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-tooltip-inner{-webkit-box-shadow:0 0 5px #000000;-moz-box-shadow:0 0 5px #000000;box-shadow:0 0 5px #000000}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0px;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-btn{border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;background-image:-moz-linear-gradient(top, #f2f2f2, #ccc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#ccc));background-image:-webkit-linear-gradient(top, #f2f2f2, #ccc);background-image:-o-linear-gradient(top, #f2f2f2, #ccc);background-image:linear-gradient(to bottom, #f2f2f2, #ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffcccccc', GradientType=0);zoom:1}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn:not(.mce-disabled):active{background-color:#d6d6d6;background-image:-moz-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#e6e6e6), to(#c0c0c0));background-image:-webkit-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:-o-linear-gradient(top, #e6e6e6, #c0c0c0);background-image:linear-gradient(to bottom, #e6e6e6, #c0c0c0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6', endColorstr='#ffc0c0c0', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-btn button{padding:4px 10px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px #fff}.mce-primary{min-width:50px;color:#fff;border:1px solid #b1b1b1;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25) rgba(0,0,0,0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #08c, #04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);zoom:1}.mce-primary:hover,.mce-primary:focus{background-color:#005fb3;background-image:-moz-linear-gradient(top, #0077b3, #003cb3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0077b3), to(#003cb3));background-image:-webkit-linear-gradient(top, #0077b3, #003cb3);background-image:-o-linear-gradient(top, #0077b3, #003cb3);background-image:linear-gradient(to bottom, #0077b3, #003cb3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0077b3', endColorstr='#ff003cb3', GradientType=0);zoom:1}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#005299;background-image:-moz-linear-gradient(top, #069, #039);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#069), to(#039));background-image:-webkit-linear-gradient(top, #069, #039);background-image:-o-linear-gradient(top, #069, #039);background-image:linear-gradient(to bottom, #069, #039);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff006699', endColorstr='#ff003399', GradientType=0);zoom:1;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px #333}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px 0 1px 0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-btn-group .mce-first{border-left:1px solid #b1b1b1;border-left:1px solid rgba(0,0,0,0.25);-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.mce-btn-group .mce-last{border-right:1px solid #b1b1b1;border-right:1px solid rgba(0,0,0,0.1);-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.mce-btn-group .mce-first.mce-last{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top, #fff, #d9d9d9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#d9d9d9));background-image:-webkit-linear-gradient(top, #fff, #d9d9d9);background-image:-o-linear-gradient(top, #fff, #d9d9d9);background-image:linear-gradient(to bottom, #fff, #d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffd9d9d9', GradientType=0);zoom:1;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-14px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;border-left:1px solid transparent;border-right:1px solid transparent}.mce-colorbutton:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:4px;margin-right:-14px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;margin-right:-17px;padding-left:0}.mce-rtl .mce-colorbutton button{padding-right:10px;padding-left:10px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px}.mce-combobox{display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox.mce-has-open input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.mce-combobox .mce-btn{border-left:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9E9E9E;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid #9e9e9e;width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);border:0;overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar{border:1px solid #c4c4c4}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:transparent;background:#e6e6e6;filter:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-menubtn.mce-disabled span{color:#aaa}.mce-menubtn span{color:#333;margin-right:2px;line-height:20px;*line-height:16px}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text{color:#fff}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:#fff}.mce-menu-item.mce-disabled:hover{background:#ccc}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:#fff}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:#fff}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#c8def4}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:#333}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:#fff}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);zoom:1}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:#cbcbcb;border-bottom:1px solid #fff;cursor:default;filter:none}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:#fff}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:2px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent;border-right:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#bdbdbd;border-right-color:#bdbdbd}.mce-splitbtn button{padding-right:4px}.mce-splitbtn .mce-open{padding-left:4px}.mce-splitbtn .mce-open.mce-active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05)}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:10px;padding-left:10px}.mce-rtl .mce-splitbtn .mce-open{padding-left:4px;padding-right:4px}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#e3e3e3;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.65)}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:before{content:"\e006"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchreplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-inserttime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-removeformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-untitled:before{content:"\e029"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:before{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:before{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-pastetext:before{content:"\e035"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#bbb} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/tinymce/themes/modern/theme.min.js b/plugins/web_gui/static/plugins/tinymce/themes/modern/theme.min.js new file mode 100644 index 0000000..ced2ffc --- /dev/null +++ b/plugins/web_gui/static/plugins/tinymce/themes/modern/theme.min.js @@ -0,0 +1 @@ +tinymce.ThemeManager.add("modern",function(e){function t(){function t(t){var i,o=[];if(t)return d(t.split(/[ ,]/),function(t){function n(){var n=e.selection;"bullist"==r&&n.selectorChanged("ul > li",function(e,n){for(var i,o=n.parents.length;o--&&(i=n.parents[o].nodeName,"OL"!=i&&"UL"!=i););t.active(e&&"UL"==i)}),"numlist"==r&&n.selectorChanged("ol > li",function(e,n){for(var i,o=n.parents.length;o--&&(i=n.parents[o].nodeName,"OL"!=i&&"UL"!=i););t.active(e&&"OL"==i)}),t.settings.stateSelector&&n.selectorChanged(t.settings.stateSelector,function(e){t.active(e)},!0),t.settings.disabledStateSelector&&n.selectorChanged(t.settings.disabledStateSelector,function(e){t.disabled(e)})}var r;"|"==t?i=null:c.has(t)?(t={type:t},u.toolbar_items_size&&(t.size=u.toolbar_items_size),o.push(t),i=null):(i||(i={type:"buttongroup",items:[]},o.push(i)),e.buttons[t]&&(r=t,t=e.buttons[r],"function"==typeof t&&(t=t()),t.type=t.type||"button",u.toolbar_items_size&&(t.size=u.toolbar_items_size),t=c.create(t),i.items.push(t),e.initialized?n():e.on("init",n)))}),n.push({type:"toolbar",layout:"flow",items:o}),!0}for(var n=[],i=1;10>i&&t(u["toolbar"+i]);i++);return n.length||t(u.toolbar||f),n}function n(){function t(t){var n;return"|"==t?{text:"|"}:n=e.menuItems[t]}function n(n){var i,o,r,s,a;if(a=tinymce.makeMap((u.removed_menuitems||"").split(/[ ,]/)),u.menu?(o=u.menu[n],s=!0):o=h[n],o){i={text:o.title},r=[],d((o.items||"").split(/[ ,]/),function(e){var n=t(e);n&&!a[e]&&r.push(t(e))}),s||d(e.menuItems,function(e){e.context==n&&("before"==e.separator&&r.push({text:"|"}),e.prependToContext?r.unshift(e):r.push(e),"after"==e.separator&&r.push({text:"|"}))});for(var l=0;l1?e:"0"+e}return"#"+i(t)+i(n)+i(r)}var r=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,i=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,o=/\s*([^:]+):\s*([^;]+);?/g,a=/\s+$/,s,l,c={},d,u="\ufeff";for(e=e||{},d=("\\\" \\' \\; \\: ; : "+u).split(" "),l=0;l-1&&n||(h[e+t]=-1==l?s[0]:s.join(" "),delete h[e+"-top"+t],delete h[e+"-right"+t],delete h[e+"-bottom"+t],delete h[e+"-left"+t])}}function d(e){var t=h[e],n;if(t){for(t=t.split(" "),n=t.length;n--;)if(t[n]!==t[0])return!1;return h[e]=t[0],!0}}function u(e,t,n,r){d(t)&&d(n)&&d(r)&&(h[e]=h[t]+" "+h[n]+" "+h[r],delete h[t],delete h[n],delete h[r])}function f(e){return b=!0,c[e]}function p(e,t){return b&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return c[e]})),t||(e=e.replace(/\\([\'\";:])/g,"$1")),e}function m(t,n,r,i,o,a){return(o=o||a)?(o=p(o),"'"+o.replace(/\'/g,"\\'")+"'"):(n=p(n||r||i),!e.allow_script_urls&&/(java|vb)script:/i.test(n.replace(/[\s\r\n]+/,""))?"":(C&&(n=C.call(x,n,"style")),"url('"+n.replace(/\'/g,"\\'")+"')"))}var h={},g,v,y,b,C=e.url_converter,x=e.url_converter_scope||this;if(t){for(t=t.replace(/[\u0000-\u001F]/g,""),t=t.replace(/\\[\"\';:\uFEFF]/g,f).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,f)});g=o.exec(t);){if(v=g[1].replace(a,"").toLowerCase(),y=g[2].replace(a,""),v&&y.length>0){if(!e.allow_script_urls&&("behavior"==v||/expression\s*\(/.test(y)))continue;"font-weight"===v&&"700"===y?y="bold":("color"===v||"background-color"===v)&&(y=y.toLowerCase()),y=y.replace(r,n),y=y.replace(i,m),h[v]=b?p(y,!0):y}o.lastIndex=g.index+g[0].length}s("border","",!0),s("border","-width"),s("border","-color"),s("border","-style"),s("padding",""),s("margin",""),u("border","border-width","border-style","border-color"),"medium none"===h.border&&delete h.border,"none"===h["border-image"]&&delete h["border-image"]}return h},serialize:function(e,n){function r(n){var r,o,a,l;if(r=t.styles[n])for(o=0,a=r.length;a>o;o++)n=r[o],l=e[n],l!==s&&l.length>0&&(i+=(i.length>0?" ":"")+n+": "+l+";")}var i="",o,a;if(n&&t&&t.styles)r("*"),r(n);else for(o in e)a=e[o],a!==s&&a.length>0&&(i+=(i.length>0?" ":"")+o+": "+a+";");return i}}}}),r(d,[],function(){function e(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r||!1):e.attachEvent&&e.attachEvent("on"+t,n)}function t(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r||!1):e.detachEvent&&e.detachEvent("on"+t,n)}function n(e,t){function n(){return!1}function r(){return!0}var i,o=t||{},l;for(i in e)s[i]||(o[i]=e[i]);if(o.target||(o.target=o.srcElement||document),e&&a.test(e.type)&&e.pageX===l&&e.clientX!==l){var c=o.target.ownerDocument||document,d=c.documentElement,u=c.body;o.pageX=e.clientX+(d&&d.scrollLeft||u&&u.scrollLeft||0)-(d&&d.clientLeft||u&&u.clientLeft||0),o.pageY=e.clientY+(d&&d.scrollTop||u&&u.scrollTop||0)-(d&&d.clientTop||u&&u.clientTop||0)}return o.preventDefault=function(){o.isDefaultPrevented=r,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},o.stopPropagation=function(){o.isPropagationStopped=r,e&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},o.stopImmediatePropagation=function(){o.isImmediatePropagationStopped=r,o.stopPropagation()},o.isDefaultPrevented||(o.isDefaultPrevented=n,o.isPropagationStopped=n,o.isImmediatePropagationStopped=n),o}function r(n,r,i){function o(){i.domLoaded||(i.domLoaded=!0,r(c))}function a(){("complete"===l.readyState||"interactive"===l.readyState)&&(t(l,"readystatechange",a),o())}function s(){try{l.documentElement.doScroll("left")}catch(e){return void setTimeout(s,0)}o()}var l=n.document,c={type:"ready"};return i.domLoaded?void r(c):(l.addEventListener?"complete"===l.readyState?o():e(n,"DOMContentLoaded",o):(e(l,"readystatechange",a),l.documentElement.doScroll&&n.self===n.top&&s()),void e(n,"load",o))}function i(){function i(e,t){var n,r,i,o,a=s[t];if(n=a&&a[e.type])for(r=0,i=n.length;i>r;r++)if(o=n[r],o&&o.func.call(o.scope,e)===!1&&e.preventDefault(),e.isImmediatePropagationStopped())return}var a=this,s={},l,c,d,u,f;c=o+(+new Date).toString(32),u="onmouseenter"in document.documentElement,d="onfocusin"in document.documentElement,f={mouseenter:"mouseover",mouseleave:"mouseout"},l=1,a.domLoaded=!1,a.events=s,a.bind=function(t,o,p,m){function h(e){i(n(e||_.event),g)}var g,v,y,b,C,x,w,_=window;if(t&&3!==t.nodeType&&8!==t.nodeType){for(t[c]?g=t[c]:(g=l++,t[c]=g,s[g]={}),m=m||t,o=o.split(" "),y=o.length;y--;)b=o[y],x=h,C=w=!1,"DOMContentLoaded"===b&&(b="ready"),a.domLoaded&&"ready"===b&&"complete"==t.readyState?p.call(m,n({type:b})):(u||(C=f[b],C&&(x=function(e){var t,r;if(t=e.currentTarget,r=e.relatedTarget,r&&t.contains)r=t.contains(r);else for(;r&&r!==t;)r=r.parentNode;r||(e=n(e||_.event),e.type="mouseout"===e.type?"mouseleave":"mouseenter",e.target=t,i(e,g))})),d||"focusin"!==b&&"focusout"!==b||(w=!0,C="focusin"===b?"focus":"blur",x=function(e){e=n(e||_.event),e.type="focus"===e.type?"focusin":"focusout",i(e,g)}),v=s[g][b],v?"ready"===b&&a.domLoaded?p({type:b}):v.push({func:p,scope:m}):(s[g][b]=v=[{func:p,scope:m}],v.fakeName=C,v.capture=w,v.nativeHandler=x,"ready"===b?r(t,x,a):e(t,C||b,x,w)));return t=v=0,p}},a.unbind=function(e,n,r){var i,o,l,d,u,f;if(!e||3===e.nodeType||8===e.nodeType)return a;if(i=e[c]){if(f=s[i],n){for(n=n.split(" "),l=n.length;l--;)if(u=n[l],o=f[u]){if(r)for(d=o.length;d--;)if(o[d].func===r){var p=o.nativeHandler;o=o.slice(0,d).concat(o.slice(d+1)),o.nativeHandler=p,f[u]=o}r&&0!==o.length||(delete f[u],t(e,o.fakeName||u,o.nativeHandler,o.capture))}}else{for(u in f)o=f[u],t(e,o.fakeName||u,o.nativeHandler,o.capture);f={}}for(u in f)return a;delete s[i];try{delete e[c]}catch(m){e[c]=null}}return a},a.fire=function(e,t,r){var o;if(!e||3===e.nodeType||8===e.nodeType)return a;r=n(null,r),r.type=t,r.target=e;do o=e[c],o&&i(r,o),e=e.parentNode||e.ownerDocument||e.defaultView||e.parentWindow;while(e&&!r.isPropagationStopped());return a},a.clean=function(e){var t,n,r=a.unbind;if(!e||3===e.nodeType||8===e.nodeType)return a;if(e[c]&&r(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(r(e),n=e.getElementsByTagName("*"),t=n.length;t--;)e=n[t],e[c]&&r(e);return a},a.destroy=function(){s={}},a.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}}var o="mce-data-",a=/^(?:mouse|contextmenu)|click/,s={keyLocation:1,layerX:1,layerY:1,returnValue:1};return i.Event=new i,i.Event.bind(window,"ready",function(){}),i}),r(u,[],function(){return function(e,t){function n(e,n,r,i){var o,a;if(e){if(!i&&e[n])return e[n];if(e!=t){if(o=e[r])return o;for(a=e.parentNode;a&&a!=t;a=a.parentNode)if(o=a[r])return o}}}var r=e;this.current=function(){return r},this.next=function(e){return r=n(r,"firstChild","nextSibling",e)},this.prev=function(e){return r=n(r,"lastChild","previousSibling",e)}}}),r(f,[],function(){function e(e,n){return n?"array"==n&&g(e)?!0:typeof e==n:e!==t}function n(e){var t=[],n,r;for(n=0,r=e.length;r>n;n++)t[n]=e[n];return t}function r(e,t,n){var r;for(e=e||[],t=t||",","string"==typeof e&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n}function i(e,n,r){var i,o;if(!e)return 0;if(r=r||e,e.length!==t){for(i=0,o=e.length;o>i;i++)if(n.call(r,e[i],i,e)===!1)return 0}else for(i in e)if(e.hasOwnProperty(i)&&n.call(r,e[i],i,e)===!1)return 0;return 1}function o(e,t){var n=[];return i(e,function(e){n.push(t(e))}),n}function a(e,t){var n=[];return i(e,function(e){(!t||t(e))&&n.push(e)}),n}function s(e,t,n){var r=this,i,o,a,s,l,c=0;if(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e),a=e[3].match(/(^|\.)(\w+)$/i)[2],o=r.createNS(e[3].replace(/\.\w+$/,""),n),!o[a]){if("static"==e[2])return o[a]=t,void(this.onCreate&&this.onCreate(e[2],e[3],o[a]));t[a]||(t[a]=function(){},c=1),o[a]=t[a],r.extend(o[a].prototype,t),e[5]&&(i=r.resolve(e[5]).prototype,s=e[5].match(/\.(\w+)$/i)[1],l=o[a],o[a]=c?function(){return i[s].apply(this,arguments)}:function(){return this.parent=i[s],l.apply(this,arguments)},o[a].prototype[a]=o[a],r.each(i,function(e,t){o[a].prototype[t]=i[t]}),r.each(t,function(e,t){i[t]?o[a].prototype[t]=function(){return this.parent=i[t],e.apply(this,arguments)}:t!=a&&(o[a].prototype[t]=e)})),r.each(t["static"],function(e,t){o[a][t]=e})}}function l(e,t){var n,r;if(e)for(n=0,r=e.length;r>n;n++)if(e[n]===t)return n;return-1}function c(e,n){var r,i,o,a=arguments,s;for(r=1,i=a.length;i>r;r++){n=a[r];for(o in n)n.hasOwnProperty(o)&&(s=n[o],s!==t&&(e[o]=s))}return e}function d(e,t,n,r){r=r||this,e&&(n&&(e=e[n]),i(e,function(e,i){return t.call(r,e,i,n)===!1?!1:void d(e,t,n,r)}))}function u(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;nn&&(t=t[e[n]],t);n++);return t}function p(t,n){return!t||e(t,"array")?t:o(t.split(n||","),h)}var m=/^\s*|\s*$/g,h=function(e){return null===e||e===t?"":(""+e).replace(m,"")},g=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return{trim:h,isArray:g,is:e,toArray:n,makeMap:r,each:i,map:o,grep:a,inArray:l,extend:c,create:s,walk:d,createNS:u,resolve:f,explode:p}}),r(p,[f],function(e){function t(n){function r(){return D.createDocumentFragment()}function i(e,t){_(z,e,t)}function o(e,t){_(F,e,t)}function a(e){i(e.parentNode,$(e))}function s(e){i(e.parentNode,$(e)+1)}function l(e){o(e.parentNode,$(e))}function c(e){o(e.parentNode,$(e)+1)}function d(e){e?(M[U]=M[V],M[q]=M[W]):(M[V]=M[U],M[W]=M[q]),M.collapsed=z}function u(e){a(e),c(e)}function f(e){i(e,0),o(e,1===e.nodeType?e.childNodes.length:e.nodeValue.length)}function p(e,t){var n=M[V],r=M[W],i=M[U],o=M[q],a=t.startContainer,s=t.startOffset,l=t.endContainer,c=t.endOffset;return 0===e?w(n,r,a,s):1===e?w(i,o,a,s):2===e?w(i,o,l,c):3===e?w(n,r,l,c):void 0}function m(){N(I)}function h(){return N(P)}function g(){return N(O)}function v(e){var t=this[V],r=this[W],i,o;3!==t.nodeType&&4!==t.nodeType||!t.nodeValue?(t.childNodes.length>0&&(o=t.childNodes[r]),o?t.insertBefore(e,o):3==t.nodeType?n.insertAfter(e,t):t.appendChild(e)):r?r>=t.nodeValue.length?n.insertAfter(e,t):(i=t.splitText(r),t.parentNode.insertBefore(e,i)):t.parentNode.insertBefore(e,t)}function y(e){var t=M.extractContents();M.insertNode(e),e.appendChild(t),M.selectNode(e)}function b(){return j(new t(n),{startContainer:M[V],startOffset:M[W],endContainer:M[U],endOffset:M[q],collapsed:M.collapsed,commonAncestorContainer:M.commonAncestorContainer})}function C(e,t){var n;if(3==e.nodeType)return e;if(0>t)return e;for(n=e.firstChild;n&&t>0;)--t,n=n.nextSibling;return n?n:e}function x(){return M[V]==M[U]&&M[W]==M[q]}function w(e,t,r,i){var o,a,s,l,c,d;if(e==r)return t==i?0:i>t?-1:1;for(o=r;o&&o.parentNode!=e;)o=o.parentNode;if(o){for(a=0,s=e.firstChild;s!=o&&t>a;)a++,s=s.nextSibling;return a>=t?-1:1}for(o=e;o&&o.parentNode!=r;)o=o.parentNode;if(o){for(a=0,s=r.firstChild;s!=o&&i>a;)a++,s=s.nextSibling;return i>a?-1:1}for(l=n.findCommonAncestor(e,r),c=e;c&&c.parentNode!=l;)c=c.parentNode;for(c||(c=l),d=r;d&&d.parentNode!=l;)d=d.parentNode;if(d||(d=l),c==d)return 0;for(s=l.firstChild;s;){if(s==c)return-1;if(s==d)return 1;s=s.nextSibling}}function _(e,t,r){var i,o;for(e?(M[V]=t,M[W]=r):(M[U]=t,M[q]=r),i=M[U];i.parentNode;)i=i.parentNode;for(o=M[V];o.parentNode;)o=o.parentNode;o==i?w(M[V],M[W],M[U],M[q])>0&&M.collapse(e):M.collapse(e),M.collapsed=x(),M.commonAncestorContainer=n.findCommonAncestor(M[V],M[U])}function N(e){var t,n=0,r=0,i,o,a,s,l,c;if(M[V]==M[U])return E(e);for(t=M[U],i=t.parentNode;i;t=i,i=i.parentNode){if(i==M[V])return k(t,e);++n}for(t=M[V],i=t.parentNode;i;t=i,i=i.parentNode){if(i==M[U])return S(t,e);++r}for(o=r-n,a=M[V];o>0;)a=a.parentNode,o--;for(s=M[U];0>o;)s=s.parentNode,o++;for(l=a.parentNode,c=s.parentNode;l!=c;l=l.parentNode,c=c.parentNode)a=l,s=c;return T(a,s,e)}function E(e){var t,n,i,o,a,s,l,c,d;if(e!=I&&(t=r()),M[W]==M[q])return t;if(3==M[V].nodeType){if(n=M[V].nodeValue,i=n.substring(M[W],M[q]),e!=O&&(o=M[V],c=M[W],d=M[q]-M[W],0===c&&d>=o.nodeValue.length-1?o.parentNode.removeChild(o):o.deleteData(c,d),M.collapse(z)),e==I)return;return i.length>0&&t.appendChild(D.createTextNode(i)),t}for(o=C(M[V],M[W]),a=M[q]-M[W];o&&a>0;)s=o.nextSibling,l=L(o,e),t&&t.appendChild(l),--a,o=s;return e!=O&&M.collapse(z),t}function k(e,t){var n,i,o,a,s,l;if(t!=I&&(n=r()),i=R(e,t),n&&n.appendChild(i),o=$(e),a=o-M[W],0>=a)return t!=O&&(M.setEndBefore(e),M.collapse(F)),n;for(i=e.previousSibling;a>0;)s=i.previousSibling,l=L(i,t),n&&n.insertBefore(l,n.firstChild),--a,i=s;return t!=O&&(M.setEndBefore(e),M.collapse(F)),n}function S(e,t){var n,i,o,a,s,l;for(t!=I&&(n=r()),o=A(e,t),n&&n.appendChild(o),i=$(e),++i,a=M[q]-i,o=e.nextSibling;o&&a>0;)s=o.nextSibling,l=L(o,t),n&&n.appendChild(l),--a,o=s;return t!=O&&(M.setStartAfter(e),M.collapse(z)),n}function T(e,t,n){var i,o,a,s,l,c,d,u;for(n!=I&&(o=r()),i=A(e,n),o&&o.appendChild(i),a=e.parentNode,s=$(e),l=$(t),++s,c=l-s,d=e.nextSibling;c>0;)u=d.nextSibling,i=L(d,n),o&&o.appendChild(i),d=u,--c;return i=R(t,n),o&&o.appendChild(i),n!=O&&(M.setStartAfter(e),M.collapse(z)),o}function R(e,t){var n=C(M[U],M[q]-1),r,i,o,a,s,l=n!=M[U];if(n==e)return B(n,l,F,t);for(r=n.parentNode,i=B(r,F,F,t);r;){for(;n;)o=n.previousSibling,a=B(n,l,F,t),t!=I&&i.insertBefore(a,i.firstChild),l=z,n=o;if(r==e)return i;n=r.previousSibling,r=r.parentNode,s=B(r,F,F,t),t!=I&&s.appendChild(i),i=s}}function A(e,t){var n=C(M[V],M[W]),r=n!=M[V],i,o,a,s,l;if(n==e)return B(n,r,z,t);for(i=n.parentNode,o=B(i,F,z,t);i;){for(;n;)a=n.nextSibling,s=B(n,r,z,t),t!=I&&o.appendChild(s),r=z,n=a;if(i==e)return o;n=i.nextSibling,i=i.parentNode,l=B(i,F,z,t),t!=I&&l.appendChild(o),o=l}}function B(e,t,r,i){var o,a,s,l,c;if(t)return L(e,i);if(3==e.nodeType){if(o=e.nodeValue,r?(l=M[W],a=o.substring(l),s=o.substring(0,l)):(l=M[q],a=o.substring(0,l),s=o.substring(l)),i!=O&&(e.nodeValue=s),i==I)return;return c=n.clone(e,F),c.nodeValue=a,c}if(i!=I)return n.clone(e,F)}function L(e,t){return t!=I?t==O?n.clone(e,z):e:void e.parentNode.removeChild(e)}function H(){return n.create("body",null,g()).outerText}var M=this,D=n.doc,P=0,O=1,I=2,z=!0,F=!1,W="startOffset",V="startContainer",U="endContainer",q="endOffset",j=e.extend,$=n.nodeIndex;return j(M,{startContainer:D,startOffset:0,endContainer:D,endOffset:0,collapsed:z,commonAncestorContainer:D,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:i,setEnd:o,setStartBefore:a,setStartAfter:s,setEndBefore:l,setEndAfter:c,collapse:d,selectNode:u,selectNodeContents:f,compareBoundaryPoints:p,deleteContents:m,extractContents:h,cloneContents:g,insertNode:v,surroundContents:y,cloneRange:b,toStringIE:H}),M}return t.prototype.toString=function(){return this.toStringIE()},t}),r(m,[f],function(e){function t(e){var t;return t=document.createElement("div"),t.innerHTML=e,t.textContent||t.innerText||e}function n(e,t){var n,r,i,a={};if(e){for(e=e.split(","),t=t||10,n=0;n\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,c=/[<>&\"\']/g,d=/&(#x|#)?([\w]+);/g,u={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};o={'"':""","'":"'","<":"<",">":">","&":"&"},a={"<":"<",">":">","&":"&",""":'"',"'":"'"},i=n("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);var f={encodeRaw:function(e,t){return e.replace(t?s:l,function(e){return o[e]||e})},encodeAllRaw:function(e){return(""+e).replace(c,function(e){return o[e]||e})},encodeNumeric:function(e,t){return e.replace(t?s:l,function(e){return e.length>1?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":o[e]||"&#"+e.charCodeAt(0)+";"})},encodeNamed:function(e,t,n){return n=n||i,e.replace(t?s:l,function(e){return o[e]||n[e]||e})},getEncodeFunc:function(e,t){function a(e,n){return e.replace(n?s:l,function(e){return o[e]||t[e]||"&#"+e.charCodeAt(0)+";"||e})}function c(e,n){return f.encodeNamed(e,n,t)}return t=n(t)||i,e=r(e.replace(/\+/g,",")),e.named&&e.numeric?a:e.named?t?c:f.encodeNamed:e.numeric?f.encodeNumeric:f.encodeRaw},decode:function(e){return e.replace(d,function(e,n,r){return n?(r=parseInt(r,2===n.length?16:10),r>65535?(r-=65536,String.fromCharCode(55296+(r>>10),56320+(1023&r))):u[r]||String.fromCharCode(r)):a[e]||i[e]||t(e)})}};return f}),r(h,[],function(){var e=navigator,t=e.userAgent,n,r,i,o,a,s,l;n=window.opera&&window.opera.buildNumber,r=/WebKit/.test(t),i=!r&&!n&&/MSIE/gi.test(t)&&/Explorer/gi.test(e.appName),i=i&&/MSIE (\w+)\./.exec(t)[1],o=-1==t.indexOf("Trident/")||-1==t.indexOf("rv:")&&-1==e.appName.indexOf("Netscape")?!1:11,i=i||o,a=!r&&!o&&/Gecko/.test(t),s=-1!=t.indexOf("Mac"),l=/(iPad|iPhone)/.test(t);var c=!l||t.match(/AppleWebKit\/(\d*)/)[1]>=534;return{opera:n,webkit:r,ie:i,gecko:a,mac:s,iOS:l,contentEditable:c,transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!=i,range:window.getSelection&&"Range"in window,documentMode:i?document.documentMode||7:10}}),r(g,[],function(){return function(e,t){function n(t){e.getElementsByTagName("head")[0].appendChild(t)}function r(t,r,s){function l(){for(var e=v.passed,t=e.length;t--;)e[t]();v.status=2,v.passed=[],v.failed=[]}function c(){for(var e=v.failed,t=e.length;t--;)e[t]();v.status=3,v.passed=[],v.failed=[]}function d(){var e=navigator.userAgent.match(/WebKit\/(\d*)/);return!!(e&&e[1]<536)}function u(e,t){e()||((new Date).getTime()-g0)return h=e.createElement("style"),h.textContent='@import "'+t+'"',p(),void n(h);f()}n(m),m.href=t}}var i=0,o={},a;t=t||{},a=t.maxLoadTime||5e3,this.load=r}}),r(v,[l,c,d,u,p,m,h,f,g],function(e,n,r,i,o,a,s,l,c){function d(e,t){var i=this,o;i.doc=e,i.win=window,i.files={},i.counter=0,i.stdMode=!v||e.documentMode>=8,i.boxModel=!v||"CSS1Compat"==e.compatMode||i.stdMode,i.hasOuterHTML="outerHTML"in e.createElement("a"),i.styleSheetLoader=new c(e),this.boundEvents=[],i.settings=t=h({keep_values:!1,hex_colors:1},t),i.schema=t.schema,i.styles=new n({url_converter:t.url_converter,url_converter_scope:t.url_converter_scope},t.schema),i.fixDoc(e),i.events=t.ownEvents?new r(t.proxy):r.Event,o=t.schema?t.schema.getBlockElements():{},i.isBlock=function(e){if(!e)return!1;var t=e.nodeType;return t?!(1!==t||!o[e.nodeName]):!!o[e]}}var u=l.each,f=l.is,p=l.grep,m=l.trim,h=l.extend,g=s.webkit,v=s.ie,y=/^([a-z0-9],?)+$/i,b=/^[ \t\r\n]*$/,C=l.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," ");return d.prototype={root:null,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},fixDoc:function(e){var t=this.settings,n;if(v&&t.schema){"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video".replace(/\w+/g,function(t){e.createElement(t)});for(n in t.schema.getCustomElements())e.createElement(n)}},clone:function(e,t){var n=this,r,i;return!v||1!==e.nodeType||t?e.cloneNode(t):(i=n.doc,t?r.firstChild:(r=i.createElement(e.nodeName),u(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),r))},getRoot:function(){var e=this;return e.get(e.settings.root_element)||e.doc.body},getViewPort:function(e){var t,n;return e=e?e:this.win,t=e.document,n=this.boxModel?t.documentElement:t.body,{x:e.pageXOffset||n.scrollLeft,y:e.pageYOffset||n.scrollTop,w:e.innerWidth||n.clientWidth,h:e.innerHeight||n.clientHeight}},getRect:function(e){var t=this,n,r;return e=t.get(e),n=t.getPos(e),r=t.getSize(e),{x:n.x,y:n.y,w:r.w,h:r.h}},getSize:function(e){var t=this,n,r;return e=t.get(e),n=t.getStyle(e,"width"),r=t.getStyle(e,"height"),-1===n.indexOf("px")&&(n=0),-1===r.indexOf("px")&&(r=0),{w:parseInt(n,10)||e.offsetWidth||e.clientWidth,h:parseInt(r,10)||e.offsetHeight||e.clientHeight}},getParent:function(e,t,n){return this.getParents(e,t,n,!1)},getParents:function(e,n,r,i){var o=this,a,s=[];for(e=o.get(e),i=i===t,r=r||("BODY"!=o.getRoot().nodeName?o.getRoot().parentNode:null),f(n,"string")&&(a=n,n="*"===n?function(e){return 1==e.nodeType}:function(e){return o.is(e,a)});e&&e!=r&&e.nodeType&&9!==e.nodeType;){if(!n||n(e)){if(!i)return e;s.push(e)}e=e.parentNode}return i?s:null},get:function(e){var t;return e&&this.doc&&"string"==typeof e&&(t=e,e=this.doc.getElementById(e),e&&e.id!==t)?this.doc.getElementsByName(t)[1]:e},getNext:function(e,t){return this._findSib(e,t,"nextSibling")},getPrev:function(e,t){return this._findSib(e,t,"previousSibling")},select:function(t,n){var r=this;return e(t,r.get(n)||r.get(r.settings.root_element)||r.doc,[])},is:function(n,r){var i;if(n.length===t){if("*"===r)return 1==n.nodeType;if(y.test(r)){for(r=r.toLowerCase().split(/,/),n=n.nodeName.toLowerCase(),i=r.length-1;i>=0;i--)if(r[i]==n)return!0;return!1}}return n.nodeType&&1!=n.nodeType?!1:e.matches(r,n.nodeType?[n]:n).length>0},add:function(e,t,n,r,i){var o=this;return this.run(e,function(e){var a;return a=f(t,"string")?o.doc.createElement(t):t,o.setAttribs(a,n),r&&(r.nodeType?a.appendChild(r):o.setHTML(a,r)),i?a:e.appendChild(a)})},create:function(e,t,n){return this.add(this.doc.createElement(e),e,t,n,1)},createHTML:function(e,t,n){var r="",i;r+="<"+e;for(i in t)t.hasOwnProperty(i)&&null!==t[i]&&(r+=" "+i+'="'+this.encode(t[i])+'"');return"undefined"!=typeof n?r+">"+n+"":r+" />"},createFragment:function(e){var t,n,r=this.doc,i;for(i=r.createElement("div"),t=r.createDocumentFragment(),e&&(i.innerHTML=e);n=i.firstChild;)t.appendChild(n);return t},remove:function(e,t){return this.run(e,function(e){var n,r=e.parentNode;if(!r)return null;if(t)for(;n=e.firstChild;)!v||3!==n.nodeType||n.nodeValue?r.insertBefore(n,e):e.removeChild(n);return r.removeChild(e)})},setStyle:function(e,t,n){return this.run(e,function(e){var r=this,i,o;if(t)if("string"==typeof t){i=e.style,t=t.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"number"!=typeof n||C[t]||(n+="px"),"opacity"===t&&e.runtimeStyle&&"undefined"==typeof e.runtimeStyle.opacity&&(i.filter=""===n?"":"alpha(opacity="+100*n+")"),"float"==t&&(t="cssFloat"in e.style?"cssFloat":"styleFloat");try{i[t]=n}catch(a){}r.settings.update_styles&&e.removeAttribute("data-mce-style")}else for(o in t)r.setStyle(e,o,t[o])})},getStyle:function(e,n,r){if(e=this.get(e)){if(this.doc.defaultView&&r){n=n.replace(/[A-Z]/g,function(e){return"-"+e});try{return this.doc.defaultView.getComputedStyle(e,null).getPropertyValue(n)}catch(i){return null}}return n=n.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"float"==n&&(n=v?"styleFloat":"cssFloat"),e.currentStyle&&r?e.currentStyle[n]:e.style?e.style[n]:t}},setStyles:function(e,t){this.setStyle(e,t)},css:function(e,t,n){this.setStyle(e,t,n)},removeAllAttribs:function(e){return this.run(e,function(e){var t,n=e.attributes;for(t=n.length-1;t>=0;t--)e.removeAttributeNode(n.item(t))})},setAttrib:function(e,t,n){var r=this;if(e&&t)return this.run(e,function(e){var i=r.settings,o=e.getAttribute(t);if(null!==n)switch(t){case"style":if(!f(n,"string"))return void u(n,function(t,n){r.setStyle(e,n,t)});i.keep_values&&(n?e.setAttribute("data-mce-style",n,2):e.removeAttribute("data-mce-style",2)),e.style.cssText=n;break;case"class":e.className=n||"";break;case"src":case"href":i.keep_values&&(i.url_converter&&(n=i.url_converter.call(i.url_converter_scope||r,n,t,e)),r.setAttrib(e,"data-mce-"+t,n,2));break;case"shape":e.setAttribute("data-mce-style",n)}f(n)&&null!==n&&0!==n.length?e.setAttribute(t,""+n,2):e.removeAttribute(t,2),o!=n&&i.onSetAttrib&&i.onSetAttrib({attrElm:e,attrName:t,attrValue:n})})},setAttribs:function(e,t){var n=this;return this.run(e,function(e){u(t,function(t,r){n.setAttrib(e,r,t)})})},getAttrib:function(e,t,n){var r,i=this,o;if(e=i.get(e),!e||1!==e.nodeType)return n===o?!1:n;if(f(n)||(n=""),/^(src|href|style|coords|shape)$/.test(t)&&(r=e.getAttribute("data-mce-"+t)))return r;if(v&&i.props[t]&&(r=e[i.props[t]],r=r&&r.nodeValue?r.nodeValue:r),r||(r=e.getAttribute(t,2)),/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(t))return e[i.props[t]]===!0&&""===r?t:r?t:"";if("FORM"===e.nodeName&&e.getAttributeNode(t))return e.getAttributeNode(t).nodeValue;if("style"===t&&(r=r||e.style.cssText,r&&(r=i.serializeStyle(i.parseStyle(r),e.nodeName),i.settings.keep_values&&e.setAttribute("data-mce-style",r))),g&&"class"===t&&r&&(r=r.replace(/(apple|webkit)\-[a-z\-]+/gi,"")),v)switch(t){case"rowspan":case"colspan":1===r&&(r="");break;case"size":("+0"===r||20===r||0===r)&&(r="");break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":0===r&&(r="");break;case"hspace":-1===r&&(r="");break;case"maxlength":case"tabindex":(32768===r||2147483647===r||"32768"===r)&&(r="");break;case"multiple":case"compact":case"noshade":case"nowrap":return 65535===r?t:n;case"shape":r=r.toLowerCase();break;default:0===t.indexOf("on")&&r&&(r=(""+r).replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1")) +}return r!==o&&null!==r&&""!==r?""+r:n},getPos:function(e,t){var n=this,r=0,i=0,o,a=n.doc,s;if(e=n.get(e),t=t||a.body,e){if(t===a.body&&e.getBoundingClientRect)return s=e.getBoundingClientRect(),t=n.boxModel?a.documentElement:a.body,r=s.left+(a.documentElement.scrollLeft||a.body.scrollLeft)-t.clientLeft,i=s.top+(a.documentElement.scrollTop||a.body.scrollTop)-t.clientTop,{x:r,y:i};for(o=e;o&&o!=t&&o.nodeType;)r+=o.offsetLeft||0,i+=o.offsetTop||0,o=o.offsetParent;for(o=e.parentNode;o&&o!=t&&o.nodeType;)r-=o.scrollLeft||0,i-=o.scrollTop||0,o=o.parentNode}return{x:r,y:i}},parseStyle:function(e){return this.styles.parse(e)},serializeStyle:function(e,t){return this.styles.serialize(e,t)},addStyle:function(e){var t=this,n=t.doc,r,i;if(t!==d.DOM&&n===document){var o=d.DOM.addedStyles;if(o=o||[],o[e])return;o[e]=!0,d.DOM.addedStyles=o}i=n.getElementById("mceDefaultStyles"),i||(i=n.createElement("style"),i.id="mceDefaultStyles",i.type="text/css",r=n.getElementsByTagName("head")[0],r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i)),i.styleSheet?i.styleSheet.cssText+=e:i.appendChild(n.createTextNode(e))},loadCSS:function(e){var t=this,n=t.doc,r;return t!==d.DOM&&n===document?void d.DOM.loadCSS(e):(e||(e=""),r=n.getElementsByTagName("head")[0],void u(e.split(","),function(e){var i;t.files[e]||(t.files[e]=!0,i=t.create("link",{rel:"stylesheet",href:e}),v&&n.documentMode&&n.recalc&&(i.onload=function(){n.recalc&&n.recalc(),i.onload=null}),r.appendChild(i))}))},addClass:function(e,t){return this.run(e,function(e){var n;return t?this.hasClass(e,t)?e.className:(n=this.removeClass(e,t),e.className=n=(""!==n?n+" ":"")+t,n):0})},removeClass:function(e,t){var n=this,r;return n.run(e,function(e){var i;return n.hasClass(e,t)?(r||(r=new RegExp("(^|\\s+)"+t+"(\\s+|$)","g")),i=e.className.replace(r," "),i=m(" "!=i?i:""),e.className=i,i||(e.removeAttribute("class"),e.removeAttribute("className")),i):e.className})},hasClass:function(e,t){return e=this.get(e),e&&t?-1!==(" "+e.className+" ").indexOf(" "+t+" "):!1},toggleClass:function(e,n,r){r=r===t?!this.hasClass(e,n):r,this.hasClass(e,n)!==r&&(r?this.addClass(e,n):this.removeClass(e,n))},show:function(e){return this.setStyle(e,"display","block")},hide:function(e){return this.setStyle(e,"display","none")},isHidden:function(e){return e=this.get(e),!e||"none"==e.style.display||"none"==this.getStyle(e,"display")},uniqueId:function(e){return(e?e:"mce_")+this.counter++},setHTML:function(e,t){var n=this;return n.run(e,function(e){if(v){for(;e.firstChild;)e.removeChild(e.firstChild);try{e.innerHTML="
    "+t,e.removeChild(e.firstChild)}catch(r){var i=n.create("div");i.innerHTML="
    "+t,u(p(i.childNodes),function(t,n){n&&e.canHaveHTML&&e.appendChild(t)})}}else e.innerHTML=t;return t})},getOuterHTML:function(e){var t,n=this;return(e=n.get(e))?1===e.nodeType&&n.hasOuterHTML?e.outerHTML:(t=(e.ownerDocument||n.doc).createElement("body"),t.appendChild(e.cloneNode(!0)),t.innerHTML):null},setOuterHTML:function(e,t,n){var r=this;return r.run(e,function(e){function i(){var i,o;for(o=n.createElement("body"),o.innerHTML=t,i=o.lastChild;i;)r.insertAfter(i.cloneNode(!0),e),i=i.previousSibling;r.remove(e)}if(1==e.nodeType)if(n=n||e.ownerDocument||r.doc,v)try{1==e.nodeType&&r.hasOuterHTML?e.outerHTML=t:i()}catch(o){i()}else i()})},decode:a.decode,encode:a.encodeAllRaw,insertAfter:function(e,t){return t=this.get(t),this.run(e,function(e){var n,r;return n=t.parentNode,r=t.nextSibling,r?n.insertBefore(e,r):n.appendChild(e),e})},replace:function(e,t,n){var r=this;return r.run(t,function(t){return f(t,"array")&&(e=e.cloneNode(!0)),n&&u(p(t.childNodes),function(t){e.appendChild(t)}),t.parentNode.replaceChild(e,t)})},rename:function(e,t){var n=this,r;return e.nodeName!=t.toUpperCase()&&(r=n.create(t),u(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),n.replace(r,e,1)),r||e},findCommonAncestor:function(e,t){for(var n=e,r;n;){for(r=t;r&&n!=r;)r=r.parentNode;if(n==r)break;n=n.parentNode}return!n&&e.ownerDocument?e.ownerDocument.documentElement:n},toHex:function(e){return this.styles.toHex(l.trim(e))},run:function(e,t,n){var r=this,i;return"string"==typeof e&&(e=r.get(e)),e?(n=n||this,e.nodeType||!e.length&&0!==e.length?t.call(n,e):(i=[],u(e,function(e,o){e&&("string"==typeof e&&(e=r.get(e)),i.push(t.call(n,e,o)))}),i)):!1},getAttribs:function(e){var t;if(e=this.get(e),!e)return[];if(v){if(t=[],"OBJECT"==e.nodeName)return e.attributes;"OPTION"===e.nodeName&&this.getAttrib(e,"selected")&&t.push({specified:1,nodeName:"selected"});var n=/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;return e.cloneNode(!1).outerHTML.replace(n,"").replace(/[\w:\-]+/gi,function(e){t.push({specified:1,nodeName:e})}),t}return e.attributes},isEmpty:function(e,t){var n=this,r,o,a,s,l,c=0;if(e=e.firstChild){s=new i(e,e.parentNode),t=t||n.schema?n.schema.getNonEmptyElements():null;do{if(a=e.nodeType,1===a){if(e.getAttribute("data-mce-bogus"))continue;if(l=e.nodeName.toLowerCase(),t&&t[l]){if("br"===l){c++;continue}return!1}for(o=n.getAttribs(e),r=e.attributes.length;r--;)if(l=e.attributes[r].nodeName,"name"===l||"data-mce-bookmark"===l)return!1}if(8==a)return!1;if(3===a&&!b.test(e.nodeValue))return!1}while(e=s.next())}return 1>=c},createRng:function(){var e=this.doc;return e.createRange?e.createRange():new o(this)},nodeIndex:function(e,t){var n=0,r,i,o;if(e)for(r=e.nodeType,e=e.previousSibling,i=e;e;e=e.previousSibling)o=e.nodeType,(!t||3!=o||o!=r&&e.nodeValue.length)&&(n++,r=o);return n},split:function(e,t,n){function r(e){function t(e){var t=e.previousSibling&&"SPAN"==e.previousSibling.nodeName,n=e.nextSibling&&"SPAN"==e.nextSibling.nodeName;return t&&n}var n,o=e.childNodes,a=e.nodeType;if(1!=a||"bookmark"!=e.getAttribute("data-mce-type")){for(n=o.length-1;n>=0;n--)r(o[n]);if(9!=a){if(3==a&&e.nodeValue.length>0){var s=m(e.nodeValue).length;if(!i.isBlock(e.parentNode)||s>0||0===s&&t(e))return}else if(1==a&&(o=e.childNodes,1==o.length&&o[0]&&1==o[0].nodeType&&"bookmark"==o[0].getAttribute("data-mce-type")&&e.parentNode.insertBefore(o[0],e),o.length||/^(br|hr|input|img)$/i.test(e.nodeName)))return;i.remove(e)}return e}}var i=this,o=i.createRng(),a,s,l;return e&&t?(o.setStart(e.parentNode,i.nodeIndex(e)),o.setEnd(t.parentNode,i.nodeIndex(t)),a=o.extractContents(),o=i.createRng(),o.setStart(t.parentNode,i.nodeIndex(t)+1),o.setEnd(e.parentNode,i.nodeIndex(e)+1),s=o.extractContents(),l=e.parentNode,l.insertBefore(r(a),e),n?l.replaceChild(n,t):l.insertBefore(t,e),l.insertBefore(r(s),e),i.remove(e),n||t):void 0},bind:function(e,t,n,r){var i=this;if(l.isArray(e)){for(var o=e.length;o--;)e[o]=i.bind(e[o],t,n,r);return e}return!i.settings.collect||e!==i.doc&&e!==i.win||i.boundEvents.push([e,t,n,r]),i.events.bind(e,t,n,r||i)},unbind:function(e,t,n){var r=this,i;if(l.isArray(e)){for(i=e.length;i--;)e[i]=r.unbind(e[i],t,n);return e}if(r.boundEvents&&(e===r.doc||e===r.win))for(i=r.boundEvents.length;i--;){var o=r.boundEvents[i];e!=o[0]||t&&t!=o[1]||n&&n!=o[2]||this.events.unbind(o[0],o[1],o[2])}return this.events.unbind(e,t,n)},fire:function(e,t,n){return this.events.fire(e,t,n)},getContentEditable:function(e){var t;return 1!=e.nodeType?null:(t=e.getAttribute("data-mce-contenteditable"),t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:null)},destroy:function(){var t=this;if(t.boundEvents){for(var n=t.boundEvents.length;n--;){var r=t.boundEvents[n];this.events.unbind(r[0],r[1],r[2])}t.boundEvents=null}e.setDocument&&e.setDocument(),t.win=t.doc=t.root=t.events=t.frag=null},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset},_findSib:function(e,t,n){var r=this,i=t;if(e)for("string"==typeof i&&(i=function(e){return r.is(e,t)}),e=e[n];e;e=e[n])if(i(e))return e;return null}},d.DOM=new d(document),d}),r(y,[v,f],function(e,t){function n(){function e(e,t){function n(){o.remove(s),a&&(a.onreadystatechange=a.onload=a=null),t()}function i(){"undefined"!=typeof console&&console.log&&console.log("Failed to load: "+e)}var o=r,a,s;s=o.uniqueId(),a=document.createElement("script"),a.id=s,a.type="text/javascript",a.src=e,"onreadystatechange"in a?a.onreadystatechange=function(){/loaded|complete/.test(a.readyState)&&n()}:a.onload=n,a.onerror=i,(document.getElementsByTagName("head")[0]||document.body).appendChild(a)}var t=0,n=1,a=2,s={},l=[],c={},d=[],u=0,f;this.isDone=function(e){return s[e]==a},this.markDone=function(e){s[e]=a},this.add=this.load=function(e,n,r){var i=s[e];i==f&&(l.push(e),s[e]=t),n&&(c[e]||(c[e]=[]),c[e].push({func:n,scope:r||this}))},this.loadQueue=function(e,t){this.loadScripts(l,e,t)},this.loadScripts=function(t,r,l){function p(e){i(c[e],function(e){e.func.call(e.scope)}),c[e]=f}var m;d.push({func:r,scope:l||this}),(m=function(){var r=o(t);t.length=0,i(r,function(t){return s[t]==a?void p(t):void(s[t]!=n&&(s[t]=n,u++,e(t,function(){s[t]=a,u--,p(t),m()})))}),u||(i(d,function(e){e.func.call(e.scope)}),d.length=0)})()}}var r=e.DOM,i=t.each,o=t.grep;return n.ScriptLoader=new n,n}),r(b,[y,f],function(e,n){function r(){var e=this;e.items=[],e.urls={},e.lookup={}}var i=n.each;return r.prototype={get:function(e){return this.lookup[e]?this.lookup[e].instance:t},dependencies:function(e){var t;return this.lookup[e]&&(t=this.lookup[e].dependencies),t||[]},requireLangPack:function(t,n){if(r.language&&r.languageLoad!==!1){if(n&&new RegExp("([, ]|\\b)"+r.language+"([, ]|\\b)").test(n)===!1)return;e.ScriptLoader.add(this.urls[t]+"/langs/"+r.language+".js")}},add:function(e,t,n){return this.items.push(t),this.lookup[e]={instance:t,dependencies:n},t},createUrl:function(e,t){return"object"==typeof t?t:{prefix:e.prefix,resource:t,suffix:e.suffix}},addComponents:function(t,n){var r=this.urls[t];i(n,function(t){e.ScriptLoader.add(r+"/"+t)})},load:function(n,o,a,s){function l(){var r=c.dependencies(n);i(r,function(e){var n=c.createUrl(o,e);c.load(n.resource,n,t,t)}),a&&a.call(s?s:e)}var c=this,d=o;c.urls[n]||("object"==typeof o&&(d=o.prefix+o.resource+o.suffix),0!==d.indexOf("/")&&-1==d.indexOf("://")&&(d=r.baseURL+"/"+d),c.urls[n]=d.substring(0,d.lastIndexOf("/")),c.lookup[n]?l():e.ScriptLoader.add(d,l,s))}},r.PluginManager=new r,r.ThemeManager=new r,r}),r(C,[],function(){function e(e,t,n){var r,i,o=n?"lastChild":"firstChild",a=n?"prev":"next";if(e[o])return e[o];if(e!==t){if(r=e[a])return r;for(i=e.parent;i&&i!==t;i=i.parent)if(r=i[a])return r}}function t(e,t){this.name=e,this.type=t,1===t&&(this.attributes=[],this.attributes.map={})}var n=/^[ \t\r\n]*$/,r={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};return t.prototype={replace:function(e){var t=this;return e.parent&&e.remove(),t.insert(e,t),t.remove(),t},attr:function(e,t){var n=this,r,i,o;if("string"!=typeof e){for(i in e)n.attr(i,e[i]);return n}if(r=n.attributes){if(t!==o){if(null===t){if(e in r.map)for(delete r.map[e],i=r.length;i--;)if(r[i].name===e)return r=r.splice(i,1),n;return n}if(e in r.map){for(i=r.length;i--;)if(r[i].name===e){r[i].value=t;break}}else r.push({name:e,value:t});return r.map[e]=t,n}return r.map[e]}},clone:function(){var e=this,n=new t(e.name,e.type),r,i,o,a,s;if(o=e.attributes){for(s=[],s.map={},r=0,i=o.length;i>r;r++)a=o[r],"id"!==a.name&&(s[s.length]={name:a.name,value:a.value},s.map[a.name]=a.value);n.attributes=s}return n.value=e.value,n.shortEnded=e.shortEnded,n},wrap:function(e){var t=this;return t.parent.insert(e,t),e.append(t),t},unwrap:function(){var e=this,t,n;for(t=e.firstChild;t;)n=t.next,e.insert(t,e,!0),t=n;e.remove()},remove:function(){var e=this,t=e.parent,n=e.next,r=e.prev;return t&&(t.firstChild===e?(t.firstChild=n,n&&(n.prev=null)):r.next=n,t.lastChild===e?(t.lastChild=r,r&&(r.next=null)):n.prev=r,e.parent=e.next=e.prev=null),e},append:function(e){var t=this,n;return e.parent&&e.remove(),n=t.lastChild,n?(n.next=e,e.prev=n,t.lastChild=e):t.lastChild=t.firstChild=e,e.parent=t,e},insert:function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,e.next=t,t.prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,e.prev=t,t.next=e),e.parent=r,e},getAll:function(t){var n=this,r,i=[];for(r=n.firstChild;r;r=e(r,n))r.name===t&&i.push(r);return i},empty:function(){var t=this,n,r,i;if(t.firstChild){for(n=[],i=t.firstChild;i;i=e(i,t))n.push(i);for(r=n.length;r--;)i=n[r],i.parent=i.firstChild=i.lastChild=i.next=i.prev=null}return t.firstChild=t.lastChild=null,t},isEmpty:function(t){var r=this,i=r.firstChild,o,a;if(i)do{if(1===i.type){if(i.attributes.map["data-mce-bogus"])continue;if(t[i.name])return!1;for(o=i.attributes.length;o--;)if(a=i.attributes[o].name,"name"===a||0===a.indexOf("data-mce-"))return!1}if(8===i.type)return!1;if(3===i.type&&!n.test(i.value))return!1}while(i=e(i,r));return!0},walk:function(t){return e(this,null,t)}},t.create=function(e,n){var i,o;if(i=new t(e,r[e]||1),n)for(o in n)i.attr(o,n[o]);return i},t}),r(x,[f],function(e){function t(e,t){return e?e.split(t||" "):[]}function n(e){function n(e,n,r){function i(e){var t={},n,r;for(n=0,r=e.length;r>n;n++)t[e[n]]={};return t}var o,l,c,d=arguments;for(r=r||[],n=n||"","string"==typeof r&&(r=t(r)),l=3;lo;o++)i.attributes[n[o]]={},i.attributesOrder.push(n[o])}var a={},s,l,c,d,u,f,p;return r[e]?r[e]:(s=t("id accesskey class dir lang style tabindex title"),l=t("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange onreset onscroll onseeked onseeking onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate onvolumechange onwaiting"),c=t("address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul"),d=t("a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment"),"html4"!=e&&(s.push.apply(s,t("contenteditable contextmenu draggable dropzone hidden spellcheck translate")),c.push.apply(c,t("article aside details dialog figure header footer hgroup section nav")),d.push.apply(d,t("audio canvas command datalist mark meter output progress time wbr video ruby bdi keygen"))),"html5-strict"!=e&&(s.push("xml:lang"),p=t("acronym applet basefont big font strike tt"),d.push.apply(d,p),o(p,function(e){n(e,"",d)}),f=t("center dir isindex noframes"),c.push.apply(c,f),u=[].concat(c,d),o(f,function(e){n(e,"",u)})),u=u||[].concat(c,d),n("html","manifest","head body"),n("head","","base command link meta noscript script style title"),n("title hr noscript br"),n("base","href target"),n("link","href rel media hreflang type sizes hreflang"),n("meta","name http-equiv content charset"),n("style","media type scoped"),n("script","src async defer type charset"),n("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",u),n("address dt dd div caption","",u),n("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",d),n("blockquote","cite",u),n("ol","reversed start type","li"),n("ul","","li"),n("li","value",u),n("dl","","dt dd"),n("a","href target rel media hreflang type",d),n("q","cite",d),n("ins del","cite datetime",u),n("img","src alt usemap ismap width height"),n("iframe","src name width height",u),n("embed","src type width height"),n("object","data type typemustmatch name usemap form width height",u,"param"),n("param","name value"),n("map","name",u,"area"),n("area","alt coords shape href target rel media hreflang type"),n("table","border","caption colgroup thead tfoot tbody tr"+("html4"==e?" col":"")),n("colgroup","span","col"),n("col","span"),n("tbody thead tfoot","","tr"),n("tr","","td th"),n("td","colspan rowspan headers",u),n("th","colspan rowspan headers scope abbr",u),n("form","accept-charset action autocomplete enctype method name novalidate target",u),n("fieldset","disabled form name",u,"legend"),n("label","form for",d),n("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),n("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"==e?u:d),n("select","disabled form multiple name required size","option optgroup"),n("optgroup","disabled label","option"),n("option","disabled label selected value"),n("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),n("menu","type label",u,"li"),n("noscript","",u),"html4"!=e&&(n("wbr"),n("ruby","",d,"rt rp"),n("figcaption","",u),n("mark rt rp summary bdi","",d),n("canvas","width height",u),n("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height",u,"track source"),n("audio","src crossorigin preload autoplay mediagroup loop muted controls",u,"track source"),n("source","src type media"),n("track","kind src srclang label default"),n("datalist","",d,"option"),n("article section nav aside header footer","",u),n("hgroup","","h1 h2 h3 h4 h5 h6"),n("figure","",u,"figcaption"),n("time","datetime",d),n("dialog","open",u),n("command","type label icon disabled checked radiogroup command"),n("output","for form name",d),n("progress","value max",d),n("meter","value min max low high optimum",d),n("details","open",u,"summary"),n("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!=e&&(i("script","language xml:space"),i("style","xml:space"),i("object","declare classid codebase codetype archive standby align border hspace vspace"),i("param","valuetype type"),i("a","charset name rev shape coords"),i("br","clear"),i("applet","codebase archive code object alt name width height align hspace vspace"),i("img","name longdesc align border hspace vspace"),i("iframe","longdesc frameborder marginwidth marginheight scrolling align"),i("font basefont","size color face"),i("input","usemap align"),i("select","onchange"),i("textarea"),i("h1 h2 h3 h4 h5 h6 div p legend caption","align"),i("ul","type compact"),i("li","type"),i("ol dl menu dir","compact"),i("pre","width xml:space"),i("hr","align noshade size width"),i("isindex","prompt"),i("table","summary width frame rules cellspacing cellpadding align bgcolor"),i("col","width align char charoff valign"),i("colgroup","width align char charoff valign"),i("thead","align char charoff valign"),i("tr","align char charoff valign bgcolor"),i("th","axis align char charoff valign nowrap bgcolor width height"),i("form","accept"),i("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),i("tfoot","align char charoff valign"),i("tbody","align char charoff valign"),i("area","nohref"),i("body","background bgcolor text link vlink alink")),"html4"!=e&&(i("input button select textarea","autofocus"),i("input textarea","placeholder"),i("a","download"),i("link script img","crossorigin"),i("iframe","srcdoc sandbox seamless allowfullscreen")),o(t("a form meter progress dfn"),function(e){a[e]&&delete a[e].children[e]}),delete a.caption.children.table,r[e]=a,a)}var r={},i=e.makeMap,o=e.each,a=e.extend,s=e.explode,l=e.inArray;return function(e){function c(t,n,o){var s=e[t];return s?s=i(s,",",i(s.toUpperCase()," ")):(s=r[t],s||(s=i(n," ",i(n.toUpperCase()," ")),s=a(s,o),r[t]=s)),s}function d(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")}function u(e){var n,r,o,a,s,c,u,f,p,m,h,g,y,C,x,w,_,N,E,k=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,S=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,T=/[*?+]/;if(e)for(e=t(e,","),v["@"]&&(w=v["@"].attributes,_=v["@"].attributesOrder),n=0,r=e.length;r>n;n++)if(s=k.exec(e[n])){if(C=s[1],p=s[2],x=s[3],f=s[5],g={},y=[],c={attributes:g,attributesOrder:y},"#"===C&&(c.paddEmpty=!0),"-"===C&&(c.removeEmpty=!0),"!"===s[4]&&(c.removeEmptyAttrs=!0),w){for(N in w)g[N]=w[N];y.push.apply(y,_)}if(f)for(f=t(f,"|"),o=0,a=f.length;a>o;o++)if(s=S.exec(f[o])){if(u={},h=s[1],m=s[2].replace(/::/g,":"),C=s[3],E=s[4],"!"===h&&(c.attributesRequired=c.attributesRequired||[],c.attributesRequired.push(m),u.required=!0),"-"===h){delete g[m],y.splice(l(y,m),1);continue}C&&("="===C&&(c.attributesDefault=c.attributesDefault||[],c.attributesDefault.push({name:m,value:E}),u.defaultValue=E),":"===C&&(c.attributesForced=c.attributesForced||[],c.attributesForced.push({name:m,value:E}),u.forcedValue=E),"<"===C&&(u.validValues=i(E,"?"))),T.test(m)?(c.attributePatterns=c.attributePatterns||[],u.pattern=d(m),c.attributePatterns.push(u)):(g[m]||y.push(m),g[m]=u)}w||"@"!=p||(w=g,_=y),x&&(c.outputName=p,v[x]=c),T.test(p)?(c.pattern=d(p),b.push(c)):v[p]=c}}function f(e){v={},b=[],u(e),o(x,function(e,t){y[t]=e.children})}function p(e){var n=/^(~)?(.+)$/;e&&o(t(e,","),function(e){var t=n.exec(e),r="~"===t[1],i=r?"span":"div",s=t[2];if(y[s]=y[i],R[s]=i,r||(k[s.toUpperCase()]={},k[s]={}),!v[s]){var l=v[i];l=a({},l),delete l.removeEmptyAttrs,delete l.removeEmpty,v[s]=l}o(y,function(e){e[i]&&(e[s]=e[i])})})}function m(e){var n=/^([+\-]?)(\w+)\[([^\]]+)\]$/;e&&o(t(e,","),function(e){var r=n.exec(e),i,a;r&&(a=r[1],i=a?y[r[2]]:y[r[2]]={"#comment":{}},i=y[r[2]],o(t(r[3],"|"),function(e){"-"===a?delete i[e]:i[e]={}}))})}function h(e){var t=v[e],n;if(t)return t;for(n=b.length;n--;)if(t=b[n],t.pattern.test(e))return t}var g=this,v={},y={},b=[],C,x,w,_,N,E,k,S,T,R={},A={};e=e||{},x=n(e.schema),e.verify_html===!1&&(e.valid_elements="*[*]"),e.valid_styles&&(C={},o(e.valid_styles,function(e,t){C[t]=s(e)})),w=c("whitespace_elements","pre script noscript style textarea video audio iframe object"),_=c("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),N=c("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"),E=c("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),S=c("non_empty_elements","td th iframe video audio object script",N),T=c("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),k=c("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup",T),o((e.special||"script noscript style textarea").split(" "),function(e){A[e]=new RegExp("]*>","gi")}),e.valid_elements?f(e.valid_elements):(o(x,function(e,t){v[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},y[t]=e.children}),"html5"!=e.schema&&o(t("strong/b em/i"),function(e){e=t(e,"/"),v[e[1]].outputName=e[0]}),v.img.attributesDefault=[{name:"alt",value:""}],o(t("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(e){v[e]&&(v[e].removeEmpty=!0)}),o(t("p h1 h2 h3 h4 h5 h6 th td pre div address caption"),function(e){v[e].paddEmpty=!0}),o(t("span"),function(e){v[e].removeEmptyAttrs=!0})),p(e.custom_elements),m(e.valid_children),u(e.extended_valid_elements),m("+ol[ul|ol],+ul[ul|ol]"),e.invalid_elements&&o(s(e.invalid_elements),function(e){v[e]&&delete v[e]}),h("span")||u("span[!data-mce-type|*]"),g.children=y,g.styles=C,g.getBoolAttrs=function(){return E},g.getBlockElements=function(){return k},g.getTextBlockElements=function(){return T},g.getShortEndedElements=function(){return N},g.getSelfClosingElements=function(){return _},g.getNonEmptyElements=function(){return S},g.getWhiteSpaceElements=function(){return w},g.getSpecialElements=function(){return A},g.isValidChild=function(e,t){var n=y[e];return!(!n||!n[t])},g.isValid=function(e,t){var n,r,i=h(e);if(i){if(!t)return!0;if(i.attributes[t])return!0;if(n=i.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},g.getElementRule=h,g.getCustomElements=function(){return R},g.addValidElements=u,g.setValidElements=f,g.addCustomElements=p,g.addValidChildren=m,g.elements=v}}),r(w,[x,m,f],function(e,t,n){var r=n.each;return function(i,o){var a=this,s=function(){};i=i||{},a.schema=o=o||new e,i.fix_self_closing!==!1&&(i.fix_self_closing=!0),r("comment cdata text start end pi doctype".split(" "),function(e){e&&(a[e]=i[e]||s)}),a.parse=function(e){function r(e){var t,n;for(t=f.length;t--&&f[t].name!==e;);if(t>=0){for(n=f.length-1;n>=t;n--)e=f[n],e.valid&&s.end(e.name);f.length=t}}function a(e,t,n,r,o){var a,s,l=/[\s\u0000-\u001F]+/g;if(t=t.toLowerCase(),n=t in C?t:z(n||r||o||""),w&&!v&&0!==t.indexOf("data-")){if(a=S[t],!a&&T){for(s=T.length;s--&&(a=T[s],!a.pattern.test(t)););-1===s&&(a=null)}if(!a)return;if(a.validValues&&!(n in a.validValues))return}if(W[t]&&!i.allow_script_urls){var c=n.replace(l,"");try{if(c=decodeURIComponent(c),V.test(c))return}catch(d){if(c=unescape(c),V.test(c))return}}p.map[t]=n,p.push({name:t,value:n})}var s=this,l,c=0,d,u,f=[],p,m,h,g,v,y,b,C,x,w,_,N,E,k,S,T,R,A,B,L,H,M,D,P,O,I=0,z=t.decode,F,W=n.makeMap("src,href"),V=/(java|vb)script:/i;for(M=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,b=o.getShortEndedElements(),H=i.self_closing_elements||o.getSelfClosingElements(),C=o.getBoolAttrs(),w=i.validate,y=i.remove_internals,F=i.fix_self_closing,P=o.getSpecialElements();l=M.exec(e);){if(c0&&f[f.length-1].name===d&&r(d),!w||(_=o.getElementRule(d))){if(N=!0,w&&(S=_.attributes,T=_.attributePatterns),(k=l[8])?(v=-1!==k.indexOf("data-mce-type"),v&&y&&(N=!1),p=[],p.map={},k.replace(D,a)):(p=[],p.map={}),w&&!v){if(R=_.attributesRequired,A=_.attributesDefault,B=_.attributesForced,L=_.removeEmptyAttrs,L&&!p.length&&(N=!1),B)for(m=B.length;m--;)E=B[m],g=E.name,O=E.value,"{$uid}"===O&&(O="mce_"+I++),p.map[g]=O,p.push({name:g,value:O});if(A)for(m=A.length;m--;)E=A[m],g=E.name,g in p.map||(O=E.value,"{$uid}"===O&&(O="mce_"+I++),p.map[g]=O,p.push({name:g,value:O}));if(R){for(m=R.length;m--&&!(R[m]in p.map););-1===m&&(N=!1)}p.map["data-mce-bogus"]&&(N=!1)}N&&s.start(d,p,x)}else N=!1;if(u=P[d]){u.lastIndex=c=l.index+l[0].length,(l=u.exec(e))?(N&&(h=e.substr(c,l.index-c)),c=l.index+l[0].length):(h=e.substr(c),c=e.length),N&&(h.length>0&&s.text(h,!0),s.end(d)),M.lastIndex=c;continue}x||(k&&k.indexOf("/")==k.length-1?N&&s.end(d):f.push({name:d,valid:N}))}else(d=l[1])?(">"===d.charAt(0)&&(d=" "+d),i.allow_conditional_comments||"[if"!==d.substr(0,3)||(d=" "+d),s.comment(d)):(d=l[2])?s.cdata(d):(d=l[3])?s.doctype(d):(d=l[4])&&s.pi(d,l[5]);c=l.index+l[0].length}for(c=0;m--)d=f[m],d.valid&&s.end(d.name)}}}),r(_,[C,x,w,f],function(e,t,n,r){var i=r.makeMap,o=r.each,a=r.explode,s=r.extend;return function(r,l){function c(t){var n,r,o,a,s,c,u,f,p,m,h,g,v,y;for(h=i("tr,td,th,tbody,thead,tfoot,table"),m=l.getNonEmptyElements(),g=l.getTextBlockElements(),n=0;n1){for(a.reverse(),s=c=d.filterNode(a[0].clone()),p=0;p0?(t.value=n,t=t.prev):(r=t.prev,t.remove(),t=r)}function g(e){var t,n={};for(t in e)"li"!==t&&"p"!=t&&(n[t]=e[t]);return n}var v,y,b,C,x,w,_,N,E,k,S,T,R,A=[],B,L,H,M,D,P,O,I;if(o=o||{},p={},m={},T=s(i("script,style,head,html,body,title,meta,param"),l.getBlockElements()),O=l.getNonEmptyElements(),P=l.children,S=r.validate,I="forced_root_block"in o?o.forced_root_block:r.forced_root_block,D=l.getWhiteSpaceElements(),R=/^[ \t\r\n]+/,L=/[ \t\r\n]+$/,H=/[ \t\r\n]+/g,M=/^[ \t\r\n]+$/,v=new n({validate:S,allow_script_urls:r.allow_script_urls,allow_conditional_comments:r.allow_conditional_comments,self_closing_elements:g(l.getSelfClosingElements()),cdata:function(e){b.append(d("#cdata",4)).value=e},text:function(e,t){var n;B||(e=e.replace(H," "),b.lastChild&&T[b.lastChild.name]&&(e=e.replace(R,""))),0!==e.length&&(n=d("#text",3),n.raw=!!t,b.append(n).value=e)},comment:function(e){b.append(d("#comment",8)).value=e},pi:function(e,t){b.append(d(e,7)).value=t,h(b)},doctype:function(e){var t;t=b.append(d("#doctype",10)),t.value=e,h(b)},start:function(e,t,n){var r,i,o,a,s;if(o=S?l.getElementRule(e):{}){for(r=d(o.outputName||e,1),r.attributes=t,r.shortEnded=n,b.append(r),s=P[b.name],s&&P[r.name]&&!s[r.name]&&A.push(r),i=f.length;i--;)a=f[i].name,a in t.map&&(E=m[a],E?E.push(r):m[a]=[r]);T[e]&&h(r),n||(b=r),!B&&D[e]&&(B=!0)}},end:function(t){var n,r,i,o,a;if(r=S?l.getElementRule(t):{}){if(T[t]&&!B){if(n=b.firstChild,n&&3===n.type)if(i=n.value.replace(R,""),i.length>0)n.value=i,n=n.next;else for(o=n.next,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.next,(0===i.length||M.test(i))&&(n.remove(),n=o),n=o;if(n=b.lastChild,n&&3===n.type)if(i=n.value.replace(L,""),i.length>0)n.value=i,n=n.prev;else for(o=n.prev,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.prev,(0===i.length||M.test(i))&&(n.remove(),n=o),n=o +}if(B&&D[t]&&(B=!1),(r.removeEmpty||r.paddEmpty)&&b.isEmpty(O))if(r.paddEmpty)b.empty().append(new e("#text","3")).value="\xa0";else if(!b.attributes.map.name&&!b.attributes.map.id)return a=b.parent,b.empty().remove(),void(b=a);b=b.parent}}},l),y=b=new e(o.context||r.root_name,11),v.parse(t),S&&A.length&&(o.context?o.invalid=!0:c(A)),I&&("body"==y.name||o.isRootContent)&&a(),!o.invalid){for(k in p){for(E=u[k],C=p[k],_=C.length;_--;)C[_].parent||C.splice(_,1);for(x=0,w=E.length;w>x;x++)E[x](C,k,o)}for(x=0,w=f.length;w>x;x++)if(E=f[x],E.name in m){for(C=m[E.name],_=C.length;_--;)C[_].parent||C.splice(_,1);for(_=0,N=E.callbacks.length;N>_;_++)E.callbacks[_](C,E.name,o)}}return y},r.remove_trailing_brs&&d.addNodeFilter("br",function(t){var n,r=t.length,i,o=s({},l.getBlockElements()),a=l.getNonEmptyElements(),c,d,u,f,p,m;for(o.body=1,n=0;r>n;n++)if(i=t[n],c=i.parent,o[i.parent.name]&&i===c.lastChild){for(u=i.prev;u;){if(f=u.name,"span"!==f||"bookmark"!==u.attr("data-mce-type")){if("br"!==f)break;if("br"===f){i=null;break}}u=u.prev}i&&(i.remove(),c.isEmpty(a)&&(p=l.getElementRule(c.name),p&&(p.removeEmpty?c.remove():p.paddEmpty&&(c.empty().append(new e("#text",3)).value="\xa0"))))}else{for(d=i;c&&c.firstChild===d&&c.lastChild===d&&(d=c,!o[c.name]);)c=c.parent;d===c&&(m=new e("#text",3),m.value="\xa0",i.replace(m))}}),r.allow_html_in_named_anchor||d.addAttributeFilter("id,name",function(e){for(var t=e.length,n,r,i,o;t--;)if(o=e[t],"a"===o.name&&o.firstChild&&!o.attr("href")){i=o.parent,n=o.lastChild;do r=n.prev,i.insert(n,o),n=r;while(n)}})}}),r(N,[m,f],function(e,t){var n=t.makeMap;return function(t){var r=[],i,o,a,s,l;return t=t||{},i=t.indent,o=n(t.indent_before||""),a=n(t.indent_after||""),s=e.getEncodeFunc(t.entity_encoding||"raw",t.entities),l="html"==t.element_format,{start:function(e,t,n){var c,d,u,f;if(i&&o[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n")),r.push("<",e),t)for(c=0,d=t.length;d>c;c++)u=t[c],r.push(" ",u.name,'="',s(u.value,!0),'"');r[r.length]=!n||l?">":" />",n&&i&&a[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n"))},end:function(e){var t;r.push(""),i&&a[e]&&r.length>0&&(t=r[r.length-1],t.length>0&&"\n"!==t&&r.push("\n"))},text:function(e,t){e.length>0&&(r[r.length]=t?e:s(e))},cdata:function(e){r.push("")},comment:function(e){r.push("")},pi:function(e,t){t?r.push(""):r.push(""),i&&r.push("\n")},doctype:function(e){r.push("",i?"\n":"")},reset:function(){r.length=0},getContent:function(){return r.join("").replace(/\n$/,"")}}}}),r(E,[N,x],function(e,t){return function(n,r){var i=this,o=new e(n);n=n||{},n.validate="validate"in n?n.validate:!0,i.schema=r=r||new t,i.writer=o,i.serialize=function(e){function t(e){var n=i[e.type],s,l,c,d,u,f,p,m,h;if(n)n(e);else{if(s=e.name,l=e.shortEnded,c=e.attributes,a&&c&&c.length>1){for(f=[],f.map={},h=r.getElementRule(e.name),p=0,m=h.attributesOrder.length;m>p;p++)d=h.attributesOrder[p],d in c.map&&(u=c.map[d],f.map[d]=u,f.push({name:d,value:u}));for(p=0,m=c.length;m>p;p++)d=c[p].name,d in f.map||(u=c.map[d],f.map[d]=u,f.push({name:d,value:u}));c=f}if(o.start(e.name,c,l),!l){if(e=e.firstChild)do t(e);while(e=e.next);o.end(s)}}}var i,a;return a=n.validate,i={3:function(e){o.text(e.value,e.raw)},8:function(e){o.comment(e.value)},7:function(e){o.pi(e.name,e.value)},10:function(e){o.doctype(e.value)},4:function(e){o.cdata(e.value)},11:function(e){if(e=e.firstChild)do t(e);while(e=e.next)}},o.reset(),1!=e.type||n.inner?i[11](e):t(e),o.getContent()}}}),r(k,[v,_,m,E,C,x,h,f],function(e,t,n,r,i,o,a,s){var l=s.each,c=s.trim,d=e.DOM;return function(e,i){var s,u,f;return i&&(s=i.dom,u=i.schema),s=s||d,u=u||new o(e),e.entity_encoding=e.entity_encoding||"named",e.remove_trailing_brs="remove_trailing_brs"in e?e.remove_trailing_brs:!0,f=new t(e,u),f.addAttributeFilter("src,href,style",function(t,n){for(var r=t.length,i,o,a="data-mce-"+n,l=e.url_converter,c=e.url_converter_scope,d;r--;)i=t[r],o=i.attributes.map[a],o!==d?(i.attr(n,o.length>0?o:null),i.attr(a,null)):(o=i.attributes.map[n],"style"===n?o=s.serializeStyle(s.parseStyle(o),i.name):l&&(o=l.call(c,o,n,i.name)),i.attr(n,o.length>0?o:null))}),f.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),n.attr("class",r.length>0?r:null)}),f.addAttributeFilter("data-mce-type",function(e,t,n){for(var r=e.length,i;r--;)i=e[r],"bookmark"!==i.attributes.map["data-mce-type"]||n.cleanup||i.remove()}),f.addAttributeFilter("data-mce-expando",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),f.addNodeFilter("noscript",function(e){for(var t=e.length,r;t--;)r=e[t].firstChild,r&&(r.value=n.decode(r.value))}),f.addNodeFilter("script,style",function(e,t){function n(e){return e.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}for(var r=e.length,i,o;r--;)if(i=e[r],o=i.firstChild?i.firstChild.value:"","script"===t){var a=(i.attr("type")||"text/javascript").replace(/^mce\-/,"");i.attr("type","text/javascript"===a?null:a),o.length>0&&(i.firstChild.value="// ")}else o.length>0&&(i.firstChild.value="")}),f.addNodeFilter("#comment",function(e){for(var t=e.length,n;t--;)n=e[t],0===n.value.indexOf("[CDATA[")?(n.name="#cdata",n.type=4,n.value=n.value.replace(/^\[CDATA\[|\]\]$/g,"")):0===n.value.indexOf("mce:protected ")&&(n.name="#text",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}),f.addNodeFilter("xml:namespace,input",function(e,t){for(var n=e.length,r;n--;)r=e[n],7===r.type?r.remove():1===r.type&&("input"!==t||"type"in r.attributes.map||r.attr("type","text"))}),e.fix_list_elements&&f.addNodeFilter("ul,ol",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.parent,("ul"===r.name||"ol"===r.name)&&n.prev&&"li"===n.prev.name&&n.prev.append(n)}),f.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:u,addNodeFilter:f.addNodeFilter,addAttributeFilter:f.addAttributeFilter,serialize:function(t,n){var i=this,o,d,p,m,h;return a.ie&&s.select("script,style,select,map").length>0?(h=t.innerHTML,t=t.cloneNode(!1),s.setHTML(t,h)):t=t.cloneNode(!0),o=t.ownerDocument.implementation,o.createHTMLDocument&&(d=o.createHTMLDocument(""),l("BODY"==t.nodeName?t.childNodes:[t],function(e){d.body.appendChild(d.importNode(e,!0))}),t="BODY"!=t.nodeName?d.body.firstChild:d.body,p=s.doc,s.doc=d),n=n||{},n.format=n.format||"html",n.selection&&(n.forced_root_block=""),n.no_events||(n.node=t,i.onPreProcess(n)),m=new r(e,u),n.content=m.serialize(f.parse(c(n.getInner?t.innerHTML:s.getOuterHTML(t)),n)),n.cleanup||(n.content=n.content.replace(/\uFEFF/g,"")),n.no_events||i.onPostProcess(n),p&&(s.doc=p),n.node=null,n.content},addRules:function(e){u.addValidElements(e)},setRules:function(e){u.setValidElements(e)},onPreProcess:function(e){i&&i.fire("PreProcess",e)},onPostProcess:function(e){i&&i.fire("PostProcess",e)}}}}),r(S,[],function(){function e(e){function t(t,n){var r,i=0,o,a,s,l,c,d,u=-1,f;if(r=t.duplicate(),r.collapse(n),f=r.parentElement(),f.ownerDocument===e.dom.doc){for(;"false"===f.contentEditable;)f=f.parentNode;if(!f.hasChildNodes())return{node:f,inside:1};for(s=f.children,o=s.length-1;o>=i;)if(d=Math.floor((i+o)/2),l=s[d],r.moveToElementText(l),u=r.compareEndPoints(n?"StartToStart":"EndToEnd",t),u>0)o=d-1;else{if(!(0>u))return{node:l};i=d+1}if(0>u)for(l?r.collapse(!1):(r.moveToElementText(f),r.collapse(!0),l=f,a=!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",1)&&f==r.parentElement();)c++;else for(r.collapse(!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",-1)&&f==r.parentElement();)c++;return{node:l,position:u,offset:c,inside:a}}}function n(){function n(e){var n=t(o,e),r,i,s=0,l,c,d;if(r=n.node,i=n.offset,n.inside&&!r.hasChildNodes())return void a[e?"setStart":"setEnd"](r,0);if(i===c)return void a[e?"setStartBefore":"setEndAfter"](r);if(n.position<0){if(l=n.inside?r.firstChild:r.nextSibling,!l)return void a[e?"setStartAfter":"setEndAfter"](r);if(!i)return void(3==l.nodeType?a[e?"setStart":"setEnd"](l,0):a[e?"setStartBefore":"setEndBefore"](l));for(;l;){if(d=l.nodeValue,s+=d.length,s>=i){r=l,s-=i,s=d.length-s;break}l=l.nextSibling}}else{if(l=r.previousSibling,!l)return a[e?"setStartBefore":"setEndBefore"](r);if(!i)return void(3==r.nodeType?a[e?"setStart":"setEnd"](l,r.nodeValue.length):a[e?"setStartAfter":"setEndAfter"](l));for(;l;){if(s+=l.nodeValue.length,s>=i){r=l,s-=i;break}l=l.previousSibling}}a[e?"setStart":"setEnd"](r,s)}var o=e.getRng(),a=i.createRng(),s,l,c,d,u;if(s=o.item?o.item(0):o.parentElement(),s.ownerDocument!=i.doc)return a;if(l=e.isCollapsed(),o.item)return a.setStart(s.parentNode,i.nodeIndex(s)),a.setEnd(a.startContainer,a.startOffset+1),a;try{n(!0),l||n()}catch(f){if(-2147024809!=f.number)throw f;u=r.getBookmark(2),c=o.duplicate(),c.collapse(!0),s=c.parentElement(),l||(c=o.duplicate(),c.collapse(!1),d=c.parentElement(),d.innerHTML=d.innerHTML),s.innerHTML=s.innerHTML,r.moveToBookmark(u),o=e.getRng(),n(!0),l||n()}return a}var r=this,i=e.dom,o=!1;this.getBookmark=function(n){function r(e){var t,n,r,o,a=[];for(t=e.parentNode,n=i.getRoot().parentNode;t!=n&&9!==t.nodeType;){for(r=t.children,o=r.length;o--;)if(e===r[o]){a.push(o);break}e=t,t=t.parentNode}return a}function o(e){var n;return n=t(a,e),n?{position:n.position,offset:n.offset,indexes:r(n.node),inside:n.inside}:void 0}var a=e.getRng(),s={};return 2===n&&(a.item?s.start={ctrl:!0,indexes:r(a.item(0))}:(s.start=o(!0),e.isCollapsed()||(s.end=o()))),s},this.moveToBookmark=function(e){function t(e){var t,n,r,o;for(t=i.getRoot(),n=e.length-1;n>=0;n--)o=t.children,r=e[n],r<=o.length-1&&(t=o[r]);return t}function n(n){var i=e[n?"start":"end"],a,s,l,c;i&&(a=i.position>0,s=o.createTextRange(),s.moveToElementText(t(i.indexes)),c=i.offset,c!==l?(s.collapse(i.inside||a),s.moveStart("character",a?-c:c)):s.collapse(n),r.setEndPoint(n?"StartToStart":"EndToStart",s),n&&r.collapse(!0))}var r,o=i.doc.body;e.start&&(e.start.ctrl?(r=o.createControlRange(),r.addElement(t(e.start.indexes)),r.select()):(r=o.createTextRange(),n(!0),n(),r.select()))},this.addRange=function(t){function n(e){var t,n,a,u,m;a=i.create("a"),t=e?s:c,n=e?l:d,u=r.duplicate(),(t==f||t==f.documentElement)&&(t=p,n=0),3==t.nodeType?(t.parentNode.insertBefore(a,t),u.moveToElementText(a),u.moveStart("character",n),i.remove(a),r.setEndPoint(e?"StartToStart":"EndToEnd",u)):(m=t.childNodes,m.length?(n>=m.length?i.insertAfter(a,m[m.length-1]):t.insertBefore(a,m[n]),u.moveToElementText(a)):t.canHaveHTML&&(t.innerHTML="",a=t.firstChild,u.moveToElementText(a),u.collapse(o)),r.setEndPoint(e?"StartToStart":"EndToEnd",u),i.remove(a))}var r,a,s,l,c,d,u,f=e.dom.doc,p=f.body,m,h;if(s=t.startContainer,l=t.startOffset,c=t.endContainer,d=t.endOffset,r=p.createTextRange(),s==c&&1==s.nodeType){if(l==d&&!s.hasChildNodes()){if(s.canHaveHTML)return u=s.previousSibling,u&&!u.hasChildNodes()&&i.isBlock(u)?u.innerHTML="":u=null,s.innerHTML="",r.moveToElementText(s.lastChild),r.select(),i.doc.selection.clear(),s.innerHTML="",void(u&&(u.innerHTML=""));l=i.nodeIndex(s),s=s.parentNode}if(l==d-1)try{if(h=s.childNodes[l],a=p.createControlRange(),a.addElement(h),a.select(),m=e.getRng(),m.item&&h===m.item(0))return}catch(g){}}n(!0),n(),r.select()},this.getRangeAt=n}return e}),r(T,[h],function(e){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey},metaKeyPressed:function(t){return(e.mac?t.metaKey:t.ctrlKey)&&!t.altKey}}}),r(R,[T,f,h],function(e,t,n){return function(r,i){function o(e){return i.settings.object_resizing===!1?!1:/TABLE|IMG|DIV/.test(e.nodeName)?"false"===e.getAttribute("data-mce-resize")?!1:!0:!1}function a(t){var n,r;n=t.screenX-k,r=t.screenY-S,M=n*N[2]+A,D=r*N[3]+B,M=5>M?5:M,D=5>D?5:D,(e.modifierPressed(t)||"IMG"==x.nodeName&&N[2]*N[3]!==0)&&(M=Math.round(D/L),D=Math.round(M*L)),b.setStyles(w,{width:M,height:D}),N[2]<0&&w.clientWidth<=M&&b.setStyle(w,"left",T+(A-M)),N[3]<0&&w.clientHeight<=D&&b.setStyle(w,"top",R+(B-D)),H||(i.fire("ObjectResizeStart",{target:x,width:A,height:B}),H=!0)}function s(){function e(e,t){t&&(x.style[e]||!i.schema.isValid(x.nodeName.toLowerCase(),e)?b.setStyle(x,e,t):b.setAttrib(x,e,t))}H=!1,e("width",M),e("height",D),b.unbind(P,"mousemove",a),b.unbind(P,"mouseup",s),O!=P&&(b.unbind(O,"mousemove",a),b.unbind(O,"mouseup",s)),b.remove(w),I&&"TABLE"!=x.nodeName||l(x),i.fire("ObjectResized",{target:x,width:M,height:D}),i.nodeChanged()}function l(e,t,n){var r,l,d,u,f,p=i.getBody();r=b.getPos(e,p),T=r.x,R=r.y,f=e.getBoundingClientRect(),l=f.width||f.right-f.left,d=f.height||f.bottom-f.top,x!=e&&(h(),x=e,M=D=0),u=i.fire("ObjectSelected",{target:e}),o(e)&&!u.isDefaultPrevented()?C(_,function(e,r){function o(t){H=!0,k=t.screenX,S=t.screenY,A=x.clientWidth,B=x.clientHeight,L=B/A,N=e,w=x.cloneNode(!0),b.addClass(w,"mce-clonedresizable"),w.contentEditable=!1,w.unSelectabe=!0,b.setStyles(w,{left:T,top:R,margin:0}),w.removeAttribute("data-mce-selected"),i.getBody().appendChild(w),b.bind(P,"mousemove",a),b.bind(P,"mouseup",s),O!=P&&(b.bind(O,"mousemove",a),b.bind(O,"mouseup",s))}var c,u;return t?void(r==t&&o(n)):(c=b.get("mceResizeHandle"+r),c?b.show(c):(u=i.getBody(),c=b.add(u,"div",{id:"mceResizeHandle"+r,"data-mce-bogus":!0,"class":"mce-resizehandle",contentEditable:!1,unSelectabe:!0,style:"cursor:"+r+"-resize; margin:0; padding:0"}),b.bind(c,"mousedown",function(e){e.preventDefault(),o(e)})),void b.setStyles(c,{left:l*e[0]+T-c.offsetWidth/2,top:d*e[1]+R-c.offsetHeight/2}))}):c(),x.setAttribute("data-mce-selected","1")}function c(){var e,t;x&&x.removeAttribute("data-mce-selected");for(e in _)t=b.get("mceResizeHandle"+e),t&&(b.unbind(t),b.remove(t))}function d(e){function t(e,t){if(e)do if(e===t)return!0;while(e=e.parentNode)}var n;return C(b.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute("data-mce-selected")}),n="mousedown"==e.type?e.target:r.getNode(),n=b.getParent(n,I?"table":"table,img,hr"),t(n,i.getBody())&&(g(),t(r.getStart(),n)&&t(r.getEnd(),n)&&(!I||n!=r.getStart()&&"IMG"!==r.getStart().nodeName))?void l(n):void c()}function u(e,t,n){e&&e.attachEvent&&e.attachEvent("on"+t,n)}function f(e,t,n){e&&e.detachEvent&&e.detachEvent("on"+t,n)}function p(e){var t=e.srcElement,n,r,o,a,s,c,d;n=t.getBoundingClientRect(),c=E.clientX-n.left,d=E.clientY-n.top;for(r in _)if(o=_[r],a=t.offsetWidth*o[0],s=t.offsetHeight*o[1],Math.abs(a-c)<8&&Math.abs(s-d)<8){N=o;break}H=!0,i.getDoc().selection.empty(),l(t,r,E)}function m(e){var t=e.srcElement;if(t!=x){if(h(),0===t.id.indexOf("mceResizeHandle"))return void(e.returnValue=!1);("IMG"==t.nodeName||"TABLE"==t.nodeName)&&(c(),x=t,u(t,"resizestart",p))}}function h(){f(x,"resizestart",p)}function g(){try{i.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(e){}}function v(e){var t;if(I){t=P.body.createControlRange();try{return t.addElement(e),t.select(),!0}catch(n){}}}function y(){x=w=null,I&&(h(),f(i.getBody(),"controlselect",m))}var b=i.dom,C=t.each,x,w,_,N,E,k,S,T,R,A,B,L,H,M,D,P=i.getDoc(),O=document,I=n.ie&&n.ie<11;_={n:[.5,0,0,-1],e:[1,.5,1,0],s:[.5,1,0,1],w:[0,.5,-1,0],nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var z=".mce-content-body";return i.contentStyles.push(z+" div.mce-resizehandle {position: absolute;border: 1px solid black;background: #FFF;width: 5px;height: 5px;z-index: 10000}"+z+" .mce-resizehandle:hover {background: #000}"+z+" img[data-mce-selected], hr[data-mce-selected] {outline: 1px solid black;resize: none}"+z+" .mce-clonedresizable {position: absolute;"+(n.gecko?"":"outline: 1px dashed black;")+"opacity: .5;filter: alpha(opacity=50);z-index: 10000}"),i.on("init",function(){I?(i.on("ObjectResized",function(e){"TABLE"!=e.target.nodeName&&(c(),v(e.target))}),u(i.getBody(),"controlselect",m),i.on("mousedown",function(e){E=e})):(g(),n.ie>=11&&(i.on("mouseup",function(e){var t=e.target.nodeName;/^(TABLE|IMG|HR)$/.test(t)&&(i.selection.select(e.target,"TABLE"==t),i.nodeChanged())}),i.dom.bind(i.getBody(),"mscontrolselect",function(e){/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&e.preventDefault()}))),i.on("nodechange mousedown mouseup ResizeEditor",d),i.on("keydown keyup",function(e){x&&"TABLE"==x.nodeName&&d(e)})}),{isResizable:o,showResizeRect:l,hideResizeRect:c,updateResizeRect:d,controlSelect:v,destroy:y}}}),r(A,[u,S,R,h,f],function(e,n,r,i,o){function a(e,t,i,o){var a=this;a.dom=e,a.win=t,a.serializer=i,a.editor=o,a.controlSelection=new r(a,o),a.win.getSelection||(a.tridentSel=new n(a))}var s=o.each,l=o.grep,c=o.trim,d=i.ie,u=i.opera;return a.prototype={setCursorLocation:function(e,t){var n=this,r=n.dom.createRng();e?(r.setStart(e,t),r.setEnd(e,t),n.setRng(r),n.collapse(!1)):(n._moveEndPoint(r,n.editor.getBody(),!0),n.setRng(r))},getContent:function(e){var n=this,r=n.getRng(),i=n.dom.create("body"),o=n.getSel(),a,s,l;return e=e||{},a=s="",e.get=!0,e.format=e.format||"html",e.selection=!0,n.editor.fire("BeforeGetContent",e),"text"==e.format?n.isCollapsed()?"":r.text||(o.toString?o.toString():""):(r.cloneContents?(l=r.cloneContents(),l&&i.appendChild(l)):r.item!==t||r.htmlText!==t?(i.innerHTML="
    "+(r.item?r.item(0).outerHTML:r.htmlText),i.removeChild(i.firstChild)):i.innerHTML=r.toString(),/^\s/.test(i.innerHTML)&&(a=" "),/\s+$/.test(i.innerHTML)&&(s=" "),e.getInner=!0,e.content=n.isCollapsed()?"":a+n.serializer.serialize(i,e)+s,n.editor.fire("GetContent",e),e.content)},setContent:function(e,t){var n=this,r=n.getRng(),i,o=n.win.document,a,s;if(t=t||{format:"html"},t.set=!0,t.selection=!0,e=t.content=e,t.no_events||n.editor.fire("BeforeSetContent",t),e=t.content,r.insertNode){e+='_',r.startContainer==o&&r.endContainer==o?o.body.innerHTML=e:(r.deleteContents(),0===o.body.childNodes.length?o.body.innerHTML=e:r.createContextualFragment?r.insertNode(r.createContextualFragment(e)):(a=o.createDocumentFragment(),s=o.createElement("div"),a.appendChild(s),s.outerHTML=e,r.insertNode(a))),i=n.dom.get("__caret"),r=o.createRange(),r.setStartBefore(i),r.setEndBefore(i),n.setRng(r),n.dom.remove("__caret");try{n.setRng(r)}catch(l){}}else r.item&&(o.execCommand("Delete",!1,null),r=n.getRng()),/^\s+/.test(e)?(r.pasteHTML('_'+e),n.dom.remove("__mce_tmp")):r.pasteHTML(e);t.no_events||n.editor.fire("SetContent",t)},getStart:function(){var e=this,t=e.getRng(),n,r,i,o;if(t.duplicate||t.item){if(t.item)return t.item(0);for(i=t.duplicate(),i.collapse(1),n=i.parentElement(),n.ownerDocument!==e.dom.doc&&(n=e.dom.getRoot()),r=o=t.parentElement();o=o.parentNode;)if(o==n){n=r;break}return n}return n=t.startContainer,1==n.nodeType&&n.hasChildNodes()&&(n=n.childNodes[Math.min(n.childNodes.length-1,t.startOffset)]),n&&3==n.nodeType?n.parentNode:n},getEnd:function(){var e=this,t=e.getRng(),n,r;return t.duplicate||t.item?t.item?t.item(0):(t=t.duplicate(),t.collapse(0),n=t.parentElement(),n.ownerDocument!==e.dom.doc&&(n=e.dom.getRoot()),n&&"BODY"==n.nodeName?n.lastChild||n:n):(n=t.endContainer,r=t.endOffset,1==n.nodeType&&n.hasChildNodes()&&(n=n.childNodes[r>0?r-1:r]),n&&3==n.nodeType?n.parentNode:n)},getBookmark:function(e,t){function n(e,t){var n=0;return s(a.select(e),function(e,r){e==t&&(n=r)}),n}function r(e){function t(t){var n,r,i,o=t?"start":"end";n=e[o+"Container"],r=e[o+"Offset"],1==n.nodeType&&"TR"==n.nodeName&&(i=n.childNodes,n=i[Math.min(t?r:r-1,i.length-1)],n&&(r=t?0:n.childNodes.length,e["set"+(t?"Start":"End")](n,r)))}return t(!0),t(),e}function i(){function e(e,n){var i=e[n?"startContainer":"endContainer"],a=e[n?"startOffset":"endOffset"],s=[],l,c,d=0;if(3==i.nodeType){if(t)for(l=i.previousSibling;l&&3==l.nodeType;l=l.previousSibling)a+=l.nodeValue.length;s.push(a)}else c=i.childNodes,a>=c.length&&c.length&&(d=1,a=Math.max(0,c.length-1)),s.push(o.dom.nodeIndex(c[a],t)+d);for(;i&&i!=r;i=i.parentNode)s.push(o.dom.nodeIndex(i,t));return s}var n=o.getRng(!0),r=a.getRoot(),i={};return i.start=e(n,!0),o.isCollapsed()||(i.end=e(n)),i}var o=this,a=o.dom,l,c,d,u,f,p,m="",h;if(2==e)return p=o.getNode(),f=p?p.nodeName:null,"IMG"==f?{name:f,index:n(f,p)}:o.tridentSel?o.tridentSel.getBookmark(e):i();if(e)return{rng:o.getRng()};if(l=o.getRng(),d=a.uniqueId(),u=o.isCollapsed(),h="overflow:hidden;line-height:0px",l.duplicate||l.item){if(l.item)return p=l.item(0),f=p.nodeName,{name:f,index:n(f,p)};c=l.duplicate();try{l.collapse(),l.pasteHTML(''+m+""),u||(c.collapse(!1),l.moveToElementText(c.parentElement()),0===l.compareEndPoints("StartToEnd",c)&&c.move("character",-1),c.pasteHTML(''+m+""))}catch(g){return null}}else{if(p=o.getNode(),f=p.nodeName,"IMG"==f)return{name:f,index:n(f,p)};c=r(l.cloneRange()),u||(c.collapse(!1),c.insertNode(a.create("span",{"data-mce-type":"bookmark",id:d+"_end",style:h},m))),l=r(l),l.collapse(!0),l.insertNode(a.create("span",{"data-mce-type":"bookmark",id:d+"_start",style:h},m))}return o.moveToBookmark({id:d,keep:1}),{id:d}},moveToBookmark:function(e){function t(t){var n=e[t?"start":"end"],r,i,o,s;if(n){for(o=n[0],i=c,r=n.length-1;r>=1;r--){if(s=i.childNodes,n[r]>s.length-1)return;i=s[n[r]]}3===i.nodeType&&(o=Math.min(n[0],i.nodeValue.length)),1===i.nodeType&&(o=Math.min(n[0],i.childNodes.length)),t?a.setStart(i,o):a.setEnd(i,o)}return!0}function n(t){var n=o.get(e.id+"_"+t),r,i,a,c,d=e.keep;if(n&&(r=n.parentNode,"start"==t?(d?(r=n.firstChild,i=1):i=o.nodeIndex(n),f=p=r,m=h=i):(d?(r=n.firstChild,i=1):i=o.nodeIndex(n),p=r,h=i),!d)){for(c=n.previousSibling,a=n.nextSibling,s(l(n.childNodes),function(e){3==e.nodeType&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});n=o.get(e.id+"_"+t);)o.remove(n,1);c&&a&&c.nodeType==a.nodeType&&3==c.nodeType&&!u&&(i=c.nodeValue.length,c.appendData(a.nodeValue),o.remove(a),"start"==t?(f=p=c,m=h=i):(p=c,h=i))}}function r(e){return!o.isBlock(e)||e.innerHTML||d||(e.innerHTML='
    '),e}var i=this,o=i.dom,a,c,f,p,m,h;if(e)if(e.start){if(a=o.createRng(),c=o.getRoot(),i.tridentSel)return i.tridentSel.moveToBookmark(e);t(!0)&&t()&&i.setRng(a)}else e.id?(n("start"),n("end"),f&&(a=o.createRng(),a.setStart(r(f),m),a.setEnd(r(p),h),i.setRng(a))):e.name?i.select(o.select(e.name)[e.index]):e.rng&&i.setRng(e.rng)},select:function(e,t){var n=this,r=n.dom,i=r.createRng(),o;if(n.lastFocusBookmark=null,e){if(!t&&n.controlSelection.controlSelect(e))return;o=r.nodeIndex(e),i.setStart(e.parentNode,o),i.setEnd(e.parentNode,o+1),t&&(n._moveEndPoint(i,e,!0),n._moveEndPoint(i,e)),n.setRng(i)}return e},isCollapsed:function(){var e=this,t=e.getRng(),n=e.getSel();return!t||t.item?!1:t.compareEndPoints?0===t.compareEndPoints("StartToEnd",t):!n||t.collapsed},collapse:function(e){var t=this,n=t.getRng(),r;n.item&&(r=n.item(0),n=t.win.document.body.createTextRange(),n.moveToElementText(r)),n.collapse(!!e),t.setRng(n)},getSel:function(){var e=this.win;return e.getSelection?e.getSelection():e.document.selection},getRng:function(e){var t=this,n,r,i,o=t.win.document,a;if(!e&&t.lastFocusBookmark){var s=t.lastFocusBookmark;return s.startContainer?(r=o.createRange(),r.setStart(s.startContainer,s.startOffset),r.setEnd(s.endContainer,s.endOffset)):r=s,r}if(e&&t.tridentSel)return t.tridentSel.getRangeAt(0);try{(n=t.getSel())&&(r=n.rangeCount>0?n.getRangeAt(0):n.createRange?n.createRange():o.createRange())}catch(l){}if(d&&r&&r.setStart&&o.selection){try{a=o.selection.createRange()}catch(l){}a&&a.item&&(i=a.item(0),r=o.createRange(),r.setStartBefore(i),r.setEndAfter(i))}return r||(r=o.createRange?o.createRange():o.body.createTextRange()),r.setStart&&9===r.startContainer.nodeType&&r.collapsed&&(i=t.dom.getRoot(),r.setStart(i,0),r.setEnd(i,0)),t.selectedRange&&t.explicitRange&&(0===r.compareBoundaryPoints(r.START_TO_START,t.selectedRange)&&0===r.compareBoundaryPoints(r.END_TO_END,t.selectedRange)?r=t.explicitRange:(t.selectedRange=null,t.explicitRange=null)),r},setRng:function(e,t){var n=this,r;if(e.select)try{e.select()}catch(i){}else if(n.tridentSel){if(e.cloneRange)try{return void n.tridentSel.addRange(e)}catch(i){}}else if(r=n.getSel()){n.explicitRange=e;try{r.removeAllRanges(),r.addRange(e)}catch(i){}t===!1&&r.extend&&(r.collapse(e.endContainer,e.endOffset),r.extend(e.startContainer,e.startOffset)),n.selectedRange=r.rangeCount>0?r.getRangeAt(0):null}},setNode:function(e){var t=this;return t.setContent(t.dom.getOuterHTML(e)),e},getNode:function(){function e(e,t){for(var n=e;e&&3===e.nodeType&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}var t=this,n=t.getRng(),r,i=n.startContainer,o=n.endContainer,a=n.startOffset,s=n.endOffset,l=t.dom.getRoot();return n?n.setStart?(r=n.commonAncestorContainer,!n.collapsed&&(i==o&&2>s-a&&i.hasChildNodes()&&(r=i.childNodes[a]),3===i.nodeType&&3===o.nodeType&&(i=i.length===a?e(i.nextSibling,!0):i.parentNode,o=0===s?e(o.previousSibling,!1):o.parentNode,i&&i===o))?i:r&&3==r.nodeType?r.parentNode:r):(r=n.item?n.item(0):n.parentElement(),r.ownerDocument!==t.win.document&&(r=l),r):l},getSelectedBlocks:function(t,n){var r=this,i=r.dom,o,a,s=[];if(a=i.getRoot(),t=i.getParent(t||r.getStart(),i.isBlock),n=i.getParent(n||r.getEnd(),i.isBlock),t&&t!=a&&s.push(t),t&&n&&t!=n){o=t;for(var l=new e(t,a);(o=l.next())&&o!=n;)i.isBlock(o)&&s.push(o)}return n&&t!=n&&n!=a&&s.push(n),s},isForward:function(){var e=this.dom,t=this.getSel(),n,r;return t&&t.anchorNode&&t.focusNode?(n=e.createRng(),n.setStart(t.anchorNode,t.anchorOffset),n.collapse(!0),r=e.createRng(),r.setStart(t.focusNode,t.focusOffset),r.collapse(!0),n.compareBoundaryPoints(n.START_TO_START,r)<=0):!0},normalize:function(){function t(t){function a(t,n){for(var r=new e(t,f.getParent(t.parentNode,f.isBlock)||p);t=r[n?"prev":"next"]();)if("BR"===t.nodeName)return!0}function s(e,t){return e.previousSibling&&e.previousSibling.nodeName==t}function l(t,n){var r,a;for(n=n||c,r=new e(n,f.getParent(n.parentNode,f.isBlock)||p);m=r[t?"prev":"next"]();){if(3===m.nodeType&&m.nodeValue.length>0)return c=m,d=t?m.nodeValue.length:0,void(i=!0);if(f.isBlock(m)||h[m.nodeName.toLowerCase()])return;a=m}o&&a&&(c=a,i=!0,d=0)}var c,d,u,f=n.dom,p=f.getRoot(),m,h,g,v;if(c=r[(t?"start":"end")+"Container"],d=r[(t?"start":"end")+"Offset"],h=f.schema.getNonEmptyElements(),v=t,1==c.nodeType&&d>c.childNodes.length-1&&(v=!1),9===c.nodeType&&(c=f.getRoot(),d=0),c===p){if(v&&(m=c.childNodes[d>0?d-1:0],m&&(g=m.nodeName.toLowerCase(),h[m.nodeName]||"TABLE"==m.nodeName)))return;if(c.hasChildNodes()&&(d=Math.min(!v&&d>0?d-1:d,c.childNodes.length-1),c=c.childNodes[d],d=0,c.hasChildNodes()&&!/TABLE/.test(c.nodeName))){m=c,u=new e(c,p);do{if(3===m.nodeType&&m.nodeValue.length>0){d=v?0:m.nodeValue.length,c=m,i=!0;break}if(h[m.nodeName.toLowerCase()]){d=f.nodeIndex(m),c=m.parentNode,"IMG"!=m.nodeName||v||d++,i=!0;break}}while(m=v?u.next():u.prev())}}o&&(3===c.nodeType&&0===d&&l(!0),1===c.nodeType&&(m=c.childNodes[d],!m||"BR"!==m.nodeName||s(m,"A")||a(m)||a(m,!0)||l(!0,c.childNodes[d]))),v&&!o&&3===c.nodeType&&d===c.nodeValue.length&&l(!1),i&&r["set"+(t?"Start":"End")](c,d)}var n=this,r,i,o;d||(r=n.getRng(),o=r.collapsed,t(!0),o||t(),i&&(o&&r.collapse(!0),n.setRng(r,n.isForward())))},selectorChanged:function(e,t){var n=this,r;return n.selectorChangedData||(n.selectorChangedData={},r={},n.editor.on("NodeChange",function(e){var t=e.element,i=n.dom,o=i.getParents(t,null,i.getRoot()),a={};s(n.selectorChangedData,function(e,t){s(o,function(n){return i.is(n,t)?(r[t]||(s(e,function(e){e(!0,{node:n,selector:t,parents:o})}),r[t]=e),a[t]=e,!1):void 0})}),s(r,function(e,n){a[n]||(delete r[n],s(e,function(e){e(!1,{node:t,selector:n,parents:o})}))})})),n.selectorChangedData[e]||(n.selectorChangedData[e]=[]),n.selectorChangedData[e].push(t),n},getScrollContainer:function(){for(var e,t=this.dom.getRoot();t&&"BODY"!=t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e){function t(e){for(var t=0,n=0,r=e;r&&r.nodeType;)t+=r.offsetLeft||0,n+=r.offsetTop||0,r=r.offsetParent;return{x:t,y:n}}var n,r,i=this,o=i.dom,a=o.getRoot(),s,l;if("BODY"!=a.nodeName){var c=i.getScrollContainer();if(c)return n=t(e).y-t(c).y,l=c.clientHeight,s=c.scrollTop,void((s>n||n+25>s+l)&&(c.scrollTop=s>n?n:n-l+25))}r=o.getViewPort(i.editor.getWin()),n=o.getPos(e).y,s=r.y,l=r.h,(ns+l)&&i.editor.getWin().scrollTo(0,s>n?n:n-l+25)},_moveEndPoint:function(t,n,r){var o=n,a=new e(n,o),s=this.dom.schema.getNonEmptyElements();do{if(3==n.nodeType&&0!==c(n.nodeValue).length)return void(r?t.setStart(n,0):t.setEnd(n,n.nodeValue.length));if(s[n.nodeName])return void(r?t.setStartBefore(n):"BR"==n.nodeName?t.setEndBefore(n):t.setEndAfter(n));if(i.ie&&i.ie<11&&this.dom.isBlock(n)&&this.dom.isEmpty(n))return void(r?t.setStart(n,0):t.setEnd(n,0))}while(n=r?a.next():a.prev());"BODY"==o.nodeName&&(r?t.setStart(o,0):t.setEnd(o,o.childNodes.length))},destroy:function(){this.win=null,this.controlSelection.destroy()}},a}),r(B,[f],function(e){function t(e){this.walk=function(t,r){function i(e){var t;return t=e[0],3===t.nodeType&&t===l&&c>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===u&&e.length>0&&t===d&&3===t.nodeType&&e.splice(e.length-1,1),e}function o(e,t,n){for(var r=[];e&&e!=n;e=e[t])r.push(e);return r}function a(e,t){do{if(e.parentNode==t)return e;e=e.parentNode}while(e)}function s(e,t,n){var a=n?"nextSibling":"previousSibling";for(h=e,g=h.parentNode;h&&h!=t;h=g)g=h.parentNode,v=o(h==e?h:h[a],a),v.length&&(n||v.reverse(),r(i(v)))}var l=t.startContainer,c=t.startOffset,d=t.endContainer,u=t.endOffset,f,p,m,h,g,v,y;if(y=e.select("td.mce-item-selected,th.mce-item-selected"),y.length>0)return void n(y,function(e){r([e])});if(1==l.nodeType&&l.hasChildNodes()&&(l=l.childNodes[c]),1==d.nodeType&&d.hasChildNodes()&&(d=d.childNodes[Math.min(u-1,d.childNodes.length-1)]),l==d)return r(i([l]));for(f=e.findCommonAncestor(l,d),h=l;h;h=h.parentNode){if(h===d)return s(l,f,!0);if(h===f)break}for(h=d;h;h=h.parentNode){if(h===l)return s(d,f);if(h===f)break}p=a(l,f)||l,m=a(d,f)||d,s(l,p,!0),v=o(p==l?p:p.nextSibling,"nextSibling",m==d?m.nextSibling:m),v.length&&r(i(v)),s(d,m)},this.split=function(e){function t(e,t){return e.splitText(t)}var n=e.startContainer,r=e.startOffset,i=e.endContainer,o=e.endOffset;return n==i&&3==n.nodeType?r>0&&rr?(o-=r,n=i=t(i,o).previousSibling,o=i.nodeValue.length,r=0):o=0):(3==n.nodeType&&r>0&&r0&&o=e;e++)r.addShortcut("ctrl+"+e,"",["FormatBlock",!1,"h"+e]);r.addShortcut("ctrl+7","",["FormatBlock",!1,"p"]),r.addShortcut("ctrl+8","",["FormatBlock",!1,"div"]),r.addShortcut("ctrl+9","",["FormatBlock",!1,"address"])}function c(e){return e?O[e]:O}function d(e,t){e&&("string"!=typeof e?et(e,function(e,t){d(t,e)}):(t=t.length?t:[t],et(t,function(e){e.deep===X&&(e.deep=!e.selector),e.split===X&&(e.split=!e.selector||e.inline),e.remove===X&&e.selector&&!e.inline&&(e.remove="none"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),"string"==typeof e.classes&&(e.classes=e.classes.split(/\s+/))}),O[e]=t))}function u(e){var t;return r.dom.getParent(e,function(e){return t=r.dom.getStyle(e,"text-decoration"),t&&"none"!==t}),t}function f(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=u(e.parentNode),r.dom.getStyle(e,"color")&&t?r.dom.setStyle(e,"text-decoration",t):r.dom.getStyle(e,"textdecoration")===t&&r.dom.setStyle(e,"text-decoration",null))}function p(t,n,o){function s(e,t){t=t||h,e&&(t.onformat&&t.onformat(e,t,n,o),et(t.styles,function(t,r){I.setStyle(e,r,E(t,n))}),et(t.attributes,function(t,r){I.setAttrib(e,r,E(t,n))}),et(t.classes,function(t){t=E(t,n),I.hasClass(e,t)||I.addClass(e,t)}))}function l(){function t(t,n){var r=new e(n);for(o=r.current();o;o=r.prev())if(o.childNodes.length>1||o==t||"BR"==o.tagName)return o}var n=r.selection.getRng(),i=n.startContainer,a=n.endContainer;if(i!=a&&0===n.endOffset){var s=t(i,a),l=3==s.nodeType?s.length:s.childNodes.length;n.setEnd(s,l)}return n}function d(e,t,n,r,i){var o=[],a=-1,s,l=-1,c=-1,d;return et(e.childNodes,function(e,t){return"UL"===e.nodeName||"OL"===e.nodeName?(a=t,s=e,!1):void 0}),et(e.childNodes,function(e,n){"SPAN"===e.nodeName&&"bookmark"==I.getAttrib(e,"data-mce-type")&&(e.id==t.id+"_start"?l=n:e.id==t.id+"_end"&&(c=n))}),0>=a||a>l&&c>a?(et(tt(e.childNodes),i),0):(d=I.clone(n,K),et(tt(e.childNodes),function(e,t){(a>l&&a>t||l>a&&t>a)&&(o.push(e),e.parentNode.removeChild(e))}),a>l?e.insertBefore(d,s):l>a&&e.insertBefore(d,s.nextSibling),r.push(d),et(o,function(e){d.appendChild(e)}),d)}function u(e,r,o){var l=[],c,u,f=!0;c=h.inline||h.block,u=I.create(c),s(u),F.walk(e,function(e){function p(e){var y,C,x,_,N;return N=f,y=e.nodeName.toLowerCase(),C=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&J(e)&&(N=f,f="true"===J(e),_=!0),w(y,"br")?(v=0,void(h.block&&I.remove(e))):h.wrapper&&g(e,t,n)?void(v=0):f&&!_&&h.block&&!h.wrapper&&i(y)&&W(C,c)?(e=I.rename(e,c),s(e),l.push(e),void(v=0)):h.selector&&(et(m,function(t){"collapsed"in t&&t.collapsed!==b||I.is(e,t.selector)&&!a(e)&&(s(e,t),x=!0)}),!h.inline||x)?void(v=0):void(!f||_||!W(c,y)||!W(C,c)||!o&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||a(e)||h.inline&&V(e)?"li"==y&&r?v=d(e,r,u,l,p):(v=0,et(tt(e.childNodes),p),_&&(f=N),v=0):(v||(v=I.clone(u,K),e.parentNode.insertBefore(v,e),l.push(v)),v.appendChild(e)))}var v;et(e,p)}),h.wrap_links===!1&&et(l,function(e){function t(e){var n,r,i;if("A"===e.nodeName){for(r=I.clone(u,K),l.push(r),i=tt(e.childNodes),n=0;n1||!V(e))&&0===o)return void I.remove(e,1);if(h.inline||h.wrapper){if(h.exact||1!==o||(e=i(e)),et(m,function(t){et(I.select(t.inline,e),function(e){var r;if(t.wrap_links===!1){r=e.parentNode;do if("A"===r.nodeName)return;while(r=r.parentNode)}R(t,n,e,t.exact?e:null)})}),g(e.parentNode,t,n))return I.remove(e,1),e=0,Y;h.merge_with_parents&&I.getParent(e.parentNode,function(r){return g(r,t,n)?(I.remove(e,1),e=0,Y):void 0}),e&&h.merge_siblings!==!1&&(e=H(B(e),e),e=H(e,B(e,Y)))}})}var m=c(t),h=m[0],v,y,b=!o&&z.isCollapsed();if(h)if(o)o.nodeType?(y=I.createRng(),y.setStartBefore(o),y.setEndAfter(o),u(T(y,m),null,!0)):u(o,null,!0);else if(b&&h.inline&&!I.select("td.mce-item-selected,th.mce-item-selected").length)D("apply",t,n);else{var C=r.selection.getNode();U||!m[0].defaultBlock||I.getParent(C,I.isBlock)||p(m[0].defaultBlock),r.selection.setRng(l()),v=z.getBookmark(),u(T(z.getRng(Y),m),v),h.styles&&(h.styles.color||h.styles.textDecoration)&&(nt(C,f,"childNodes"),f(C)),z.moveToBookmark(v),P(z.getRng(Y)),r.nodeChanged()}}function m(e,t,n){function i(e){var n,r,o,a,s;if(1===e.nodeType&&J(e)&&(a=b,b="true"===J(e),s=!0),n=tt(e.childNodes),b&&!s)for(r=0,o=p.length;o>r&&!R(p[r],t,e,e);r++);if(m.deep&&n.length){for(r=0,o=n.length;o>r;r++)i(n[r]);s&&(b=a)}}function a(n){var r;return et(o(n.parentNode).reverse(),function(n){var i;r||"_start"==n.id||"_end"==n.id||(i=g(n,e,t),i&&i.split!==!1&&(r=n))}),r}function s(e,n,r,i){var o,a,s,l,c,d;if(e){for(d=e.parentNode,o=n.parentNode;o&&o!=d;o=o.parentNode){for(a=I.clone(o,K),c=0;c=0;a--){if(s=t[a].selector,!s||t[a].defaultBlock)return Y;for(i=r.length-1;i>=0;i--)if(I.is(r[i],s))return Y}return K}function C(e,t,n){var i;return G||(G={},i={},r.on("NodeChange",function(e){var t=o(e.element),n={};et(G,function(e,r){et(t,function(o){return g(o,r,{},e.similar)?(i[r]||(et(e,function(e){e(!0,{node:o,format:r,parents:t})}),i[r]=e),n[r]=e,!1):void 0})}),et(i,function(r,o){n[o]||(delete i[o],et(r,function(n){n(!1,{node:e.element,format:o,parents:t})}))})})),et(e.split(","),function(e){G[e]||(G[e]=[],G[e].similar=n),G[e].push(t)}),this}function x(e,t){return w(e,t.inline)?Y:w(e,t.block)?Y:t.selector?1==e.nodeType&&I.is(e,t.selector):void 0}function w(e,t){return e=e||"",t=t||"",e=""+(e.nodeName||e),t=""+(t.nodeName||t),e.toLowerCase()==t.toLowerCase()}function _(e,t){return N(I.getStyle(e,t),t)}function N(e,t){return("color"==t||"backgroundColor"==t)&&(e=I.toHex(e)),"fontWeight"==t&&700==e&&(e="bold"),"fontFamily"==t&&(e=e.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+e}function E(e,t){return"string"!=typeof e?e=e(t):t&&(e=e.replace(/%(\w+)/g,function(e,n){return t[n]||e})),e}function k(e){return e&&3===e.nodeType&&/^([\t \r\n]+|)$/.test(e.nodeValue)}function S(e,t,n){var r=I.create(t,n);return e.parentNode.insertBefore(r,e),r.appendChild(e),r}function T(t,n,a){function s(e){function t(e){return"BR"==e.nodeName&&e.getAttribute("data-mce-bogus")&&!e.nextSibling}var r,i,o,a,s;if(r=i=e?g:y,a=e?"previousSibling":"nextSibling",s=I.getRoot(),3==r.nodeType&&!k(r)&&(e?v>0:br?n:r,-1===n||a||n++):(n=o.indexOf(" ",t),r=o.indexOf("\xa0",t),n=-1!==n&&(-1===r||r>n)?n:r),n}var s,l,c,d;if(3===t.nodeType){if(c=o(t,n),-1!==c)return{container:t,offset:c};d=t}for(s=new e(t,I.getParent(t,V)||r.getBody());l=s[i?"prev":"next"]();)if(3===l.nodeType){if(d=l,c=o(l),-1!==c)return{container:l,offset:c}}else if(V(l))break;return d?(n=i?0:d.length,{container:d,offset:n}):void 0}function u(e,r){var i,a,s,l;for(3==e.nodeType&&0===e.nodeValue.length&&e[r]&&(e=e[r]),i=o(e),a=0;ap?p:v],3==g.nodeType&&(v=0)),1==y.nodeType&&y.hasChildNodes()&&(p=y.childNodes.length-1,y=y.childNodes[b>p?p:b-1],3==y.nodeType&&(b=y.nodeValue.length)),g=c(g),y=c(y),(L(g.parentNode)||L(g))&&(g=L(g)?g:g.parentNode,g=g.nextSibling||g,3==g.nodeType&&(v=0)),(L(y.parentNode)||L(y))&&(y=L(y)?y:y.parentNode,y=y.previousSibling||y,3==y.nodeType&&(b=y.length)),n[0].inline&&(t.collapsed&&(h=d(g,v,!0),h&&(g=h.container,v=h.offset),h=d(y,b),h&&(y=h.container,b=h.offset)),m=l(y,b),m.node)){for(;m.node&&0===m.offset&&m.node.previousSibling;)m=l(m.node.previousSibling);m.node&&m.offset>0&&3===m.node.nodeType&&" "===m.node.nodeValue.charAt(m.offset-1)&&m.offset>1&&(y=m.node,y.splitText(m.offset-1))}return(n[0].inline||n[0].block_expand)&&(n[0].inline&&3==g.nodeType&&0!==v||(g=s(!0)),n[0].inline&&3==y.nodeType&&b!==y.nodeValue.length||(y=s())),n[0].selector&&n[0].expand!==K&&!n[0].inline&&(g=u(g,"previousSibling"),y=u(y,"nextSibling")),(n[0].block||n[0].selector)&&(g=f(g,"previousSibling"),y=f(y,"nextSibling"),n[0].block&&(V(g)||(g=s(!0)),V(y)||(y=s()))),1==g.nodeType&&(v=q(g),g=g.parentNode),1==y.nodeType&&(b=q(y)+1,y=y.parentNode),{startContainer:g,startOffset:v,endContainer:y,endOffset:b}}function R(e,t,n,r){var i,o,a;if(!x(n,e))return K;if("all"!=e.remove)for(et(e.styles,function(e,i){e=N(E(e,t),i),"number"==typeof i&&(i=e,r=0),(!r||w(_(r,i),e))&&I.setStyle(n,i,""),a=1}),a&&""===I.getAttrib(n,"style")&&(n.removeAttribute("style"),n.removeAttribute("data-mce-style")),et(e.attributes,function(e,i){var o;if(e=E(e,t),"number"==typeof i&&(i=e,r=0),!r||w(I.getAttrib(r,i),e)){if("class"==i&&(e=I.getAttrib(n,i),e&&(o="",et(e.split(/\s+/),function(e){/mce\w+/.test(e)&&(o+=(o?" ":"")+e)}),o)))return void I.setAttrib(n,i,o);"class"==i&&n.removeAttribute("className"),$.test(i)&&n.removeAttribute("data-mce-"+i),n.removeAttribute(i)}}),et(e.classes,function(e){e=E(e,t),(!r||I.hasClass(r,e))&&I.removeClass(n,e)}),o=I.getAttribs(n),i=0;ia?a:o]),3===i.nodeType&&n&&o>=i.nodeValue.length&&(i=new e(i,r.getBody()).next()||i),3!==i.nodeType||n||0!==o||(i=new e(i,r.getBody()).prev()||i),i}function D(t,n,o){function a(e){var t=I.create("span",{id:y,"data-mce-bogus":!0,style:b?"color:red":""});return e&&t.appendChild(r.getDoc().createTextNode(j)),t}function s(e,t){for(;e;){if(3===e.nodeType&&e.nodeValue!==j||e.childNodes.length>1)return!1;t&&1===e.nodeType&&t.push(e),e=e.firstChild}return!0}function l(e){for(;e;){if(e.id===y)return e;e=e.parentNode}}function d(t){var n;if(t)for(n=new e(t,t),t=n.current();t;t=n.next())if(3===t.nodeType)return t}function u(e,t){var n,r;if(e)r=z.getRng(!0),s(e)?(t!==!1&&(r.setStartBefore(e),r.setEndBefore(e)),I.remove(e)):(n=d(e),n.nodeValue.charAt(0)===j&&(n=n.deleteData(0,1)),I.remove(e,1)),z.setRng(r);else if(e=l(z.getStart()),!e)for(;e=I.get(y);)u(e,!1)}function f(){var e,t,r,i,s,u,f;e=z.getRng(!0),i=e.startOffset,u=e.startContainer,f=u.nodeValue,t=l(z.getStart()),t&&(r=d(t)),f&&i>0&&i=0;p--)d.appendChild(I.clone(f[p],!1)),d=d.firstChild;d.appendChild(I.doc.createTextNode(j)),d=d.firstChild;var v=I.getParent(u,i);v&&I.isEmpty(v)?u.parentNode.replaceChild(h,u):I.insertAfter(h,u),z.setCursorLocation(d,1),I.isEmpty(u)&&I.remove(u)}}function v(){var e;e=l(z.getStart()),e&&!I.isEmpty(e)&&nt(e,function(e){1!=e.nodeType||e.id===y||I.isEmpty(e)||I.setAttrib(e,"data-mce-bogus",null)},"childNodes")}var y="_mce_caret",b=r.settings.caret_debug;r._hasCaretEvents||(Z=function(){var e=[],t;if(s(l(z.getStart()),e))for(t=e.length;t--;)I.setAttrib(e[t],"data-mce-bogus","1")},Q=function(e){var t=e.keyCode;u(),(8==t||37==t||39==t)&&u(l(z.getStart())),v()},r.on("SetContent",function(e){e.selection&&v()}),r._hasCaretEvents=!0),"apply"==t?f():h()}function P(t){var n=t.startContainer,r=t.startOffset,i,o,a,s,l;if(3==n.nodeType&&r>=n.nodeValue.length&&(r=q(n),n=n.parentNode,i=!0),1==n.nodeType)for(s=n.childNodes,n=s[Math.min(r,s.length-1)],o=new e(n,I.getParent(n,I.isBlock)),(r>s.length-1||i)&&o.next(),a=o.current();a;a=o.next())if(3==a.nodeType&&!k(a))return l=I.create("a",null,j),a.parentNode.insertBefore(l,a),t.setStart(a,0),z.setRng(t),void I.remove(l)}var O={},I=r.dom,z=r.selection,F=new t(I),W=r.schema.isValidChild,V=I.isBlock,U=r.settings.forced_root_block,q=I.nodeIndex,j="\ufeff",$=/^(src|href|style)$/,K=!1,Y=!0,G,X,J=I.getContentEditable,Q,Z,et=n.each,tt=n.grep,nt=n.walk,rt=n.extend;rt(this,{get:c,register:d,apply:p,remove:m,toggle:h,match:v,matchAll:y,matchNode:g,canApply:b,formatChanged:C}),s(),l(),r.on("BeforeGetContent",function(){Z&&Z()}),r.on("mouseup keydown",function(e){Q&&Q(e)})}}),r(H,[h,f],function(e,t){var n=t.trim,r;return r=new RegExp(["]+data-mce-bogus[^>]+>[\u200b\ufeff]+<\\/span>","]+data-mce-bogus[^>]+><\\/div>",'\\s?data-mce-selected="[^"]+"'].join("|"),"gi"),function(t){function i(){return n(t.getContent({format:"raw",no_events:1}).replace(r,""))}function o(){a.typing=!1,a.add()}var a,s=0,l=[],c,d,u;return t.on("init",function(){a.add()}),t.on("BeforeExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&a.beforeChange()}),t.on("ExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&a.add()}),t.on("ObjectResizeStart",function(){a.beforeChange()}),t.on("SaveContent ObjectResized",o),t.dom.bind(t.dom.getRoot(),"dragend",o),t.dom.bind(t.getBody(),"focusout",function(){!t.removed&&a.typing&&o()}),t.on("KeyUp",function(n){var r=n.keyCode;(r>=33&&36>=r||r>=37&&40>=r||45==r||13==r||n.ctrlKey)&&(o(),t.nodeChanged()),(46==r||8==r||e.mac&&(91==r||93==r))&&t.nodeChanged(),d&&a.typing&&(t.isDirty()||(t.isNotDirty=!l[0]||i()==l[0].content,t.isNotDirty||t.fire("change",{level:l[0],lastLevel:null})),t.fire("TypingUndo"),d=!1,t.nodeChanged())}),t.on("KeyDown",function(e){var t=e.keyCode;return t>=33&&36>=t||t>=37&&40>=t||45==t?void(a.typing&&o()):void((16>t||t>20)&&224!=t&&91!=t&&!a.typing&&(a.beforeChange(),a.typing=!0,a.add(),d=!0))}),t.on("MouseDown",function(){a.typing&&o()}),t.addShortcut("ctrl+z","","Undo"),t.addShortcut("ctrl+y,ctrl+shift+z","","Redo"),t.on("AddUndo Undo Redo ClearUndos MouseUp",function(e){e.isDefaultPrevented()||t.nodeChanged()}),a={data:l,typing:!1,beforeChange:function(){u||(c=t.selection.getBookmark(2,!0))},add:function(e){var n,r=t.settings,o;if(e=e||{},e.content=i(),u||t.fire("BeforeAddUndo",{level:e}).isDefaultPrevented())return null;if(o=l[s],o&&o.content==e.content)return null;if(l[s]&&(l[s].beforeBookmark=c),r.custom_undo_redo_levels&&l.length>r.custom_undo_redo_levels){for(n=0;n0&&(t.fire("change",a),t.isNotDirty=!1),e},undo:function(){var e;return a.typing&&(a.add(),a.typing=!1),s>0&&(e=l[--s],0===s&&(t.isNotDirty=!0),t.setContent(e.content,{format:"raw"}),t.selection.moveToBookmark(e.beforeBookmark),t.fire("undo",{level:e})),e},redo:function(){var e;return s0||a.typing&&l[0]&&i()!=l[0].content},hasRedo:function(){return sB)&&(u=o.create("br"),n.parentNode.insertBefore(u,n)),l.setStartBefore(n),l.setEndBefore(n)):(l.setStartAfter(n),l.setEndAfter(n)):(l.setStart(n,0),l.setEnd(n,0));a.setRng(l),o.remove(u),a.scrollIntoView(n)}function h(e){var t=s.forced_root_block;t&&t.toLowerCase()===e.tagName.toLowerCase()&&o.setAttribs(e,s.forced_root_block_attrs)}function g(e){var t=T,r,i,a;if(e||"TABLE"==P?(r=o.create(e||I),h(r)):r=A.cloneNode(!1),a=r,s.keep_styles!==!1)do if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(t.nodeName)){if("_mce_caret"==t.id)continue;i=t.cloneNode(!1),o.setAttrib(i,"id",""),r.hasChildNodes()?(i.appendChild(r.firstChild),r.appendChild(i)):(a=i,r.appendChild(i))}while(t=t.parentNode);return n||(a.innerHTML='
    '),r}function v(t){var n,r,i;if(3==T.nodeType&&(t?R>0:R0)return!0}function x(){var e,t,r;T&&3==T.nodeType&&R>=T.nodeValue.length&&(n||C()||(e=o.create("br"),E.insertNode(e),E.setStartAfter(e),E.setEndAfter(e),t=!0)),e=o.create("br"),E.insertNode(e),n&&"PRE"==P&&(!B||8>B)&&e.parentNode.insertBefore(o.doc.createTextNode("\r"),e),r=o.create("span",{}," "),e.parentNode.insertBefore(r,e),a.scrollIntoView(r),o.remove(r),t?(E.setStartBefore(e),E.setEndBefore(e)):(E.setStartAfter(e),E.setEndAfter(e)),a.setRng(E),l.add()}function w(e){do 3===e.nodeType&&(e.nodeValue=e.nodeValue.replace(/^[\r\n]+/,"")),e=e.firstChild;while(e)}function _(e){var t=o.getRoot(),n,r;for(n=e;n!==t&&"false"!==o.getContentEditable(n);)"true"===o.getContentEditable(n)&&(r=n),n=n.parentNode;return n!==t?r:t}function N(e){var t;n||(e.normalize(),t=e.lastChild,(!t||/^(left|right)$/gi.test(o.getStyle(t,"float",!0)))&&o.add(e,"br"))}var E=a.getRng(!0),k,S,T,R,A,B,L,H,M,D,P,O,I,z;if(!E.collapsed)return void r.execCommand("Delete");if(!i.isDefaultPrevented()&&(T=E.startContainer,R=E.startOffset,I=(s.force_p_newlines?"p":"")||s.forced_root_block,I=I?I.toUpperCase():"",B=o.doc.documentMode,L=i.shiftKey,1==T.nodeType&&T.hasChildNodes()&&(z=R>T.childNodes.length-1,T=T.childNodes[Math.min(R,T.childNodes.length-1)]||T,R=z&&3==T.nodeType?T.nodeValue.length:0),S=_(T))){if(l.beforeChange(),!o.isBlock(S)&&S!=o.getRoot())return void((!I||L)&&x());if((I&&!L||!I&&L)&&(T=y(T,R)),A=o.getParent(T,o.isBlock),D=A?o.getParent(A.parentNode,o.isBlock):null,P=A?A.nodeName.toUpperCase():"",O=D?D.nodeName.toUpperCase():"","LI"!=O||i.ctrlKey||(A=D,P=O),"LI"==P){if(!I&&L)return void x();if(o.isEmpty(A))return void b()}if("PRE"==P&&s.br_in_pre!==!1){if(!L)return void x()}else if(!I&&!L&&"LI"!=P||I&&L)return void x();I&&A===r.getBody()||(I=I||"P",v()?(H=/^(H[1-6]|PRE|FIGURE)$/.test(P)&&"HGROUP"!=O?g(I):g(),s.end_container_on_empty_block&&u(D)&&o.isEmpty(A)?H=o.split(D,A):o.insertAfter(H,A),m(H)):v(!0)?(H=A.parentNode.insertBefore(g(),A),f(H),m(A)):(k=E.cloneRange(),k.setEndAfter(A),M=k.extractContents(),w(M),H=M.firstChild,o.insertAfter(M,A),p(H),N(A),m(H)),o.setAttrib(H,"id",""),r.fire("NewBlock",{newBlock:H}),l.add())}}var o=r.dom,a=r.selection,s=r.settings,l=r.undoManager,c=r.schema,d=c.getNonEmptyElements();r.on("keydown",function(e){13==e.keyCode&&i(e)!==!1&&e.preventDefault()})}}),r(D,[],function(){return function(e){function t(){var t=i.getStart(),s=e.getBody(),l,c,d,u,f,p,m,h=-16777215,g,v,y,b,C;if(C=n.forced_root_block,t&&1===t.nodeType&&C){for(;t&&t!=s;){if(a[t.nodeName])return;t=t.parentNode}if(l=i.getRng(),l.setStart){c=l.startContainer,d=l.startOffset,u=l.endContainer,f=l.endOffset;try{v=e.getDoc().activeElement===s}catch(x){}}else l.item&&(t=l.item(0),l=e.getDoc().body.createTextRange(),l.moveToElementText(t)),v=l.parentElement().ownerDocument===e.getDoc(),y=l.duplicate(),y.collapse(!0),d=-1*y.move("character",h),y.collapsed||(y=l.duplicate(),y.collapse(!1),f=-1*y.move("character",h)-d);for(t=s.firstChild,b=s.nodeName.toLowerCase();t;)if((3===t.nodeType||1==t.nodeType&&!a[t.nodeName])&&o.isValidChild(b,C.toLowerCase())){if(3===t.nodeType&&0===t.nodeValue.length){m=t,t=t.nextSibling,r.remove(m);continue}p||(p=r.create(C,e.settings.forced_root_block_attrs),t.parentNode.insertBefore(p,t),g=!0),m=t,t=t.nextSibling,p.appendChild(m)}else p=null,t=t.nextSibling;if(g&&v){if(l.setStart)l.setStart(c,d),l.setEnd(u,f),i.setRng(l);else try{l=e.getDoc().body.createTextRange(),l.moveToElementText(s),l.collapse(!0),l.moveStart("character",d),f>0&&l.moveEnd("character",f),l.select()}catch(x){}e.nodeChanged()}}}var n=e.settings,r=e.dom,i=e.selection,o=e.schema,a=o.getBlockElements();n.forced_root_block&&e.on("NodeChange",t)}}),r(P,[E,h,f],function(e,n,r){var i=r.each,o=r.extend,a=r.map,s=r.inArray,l=r.explode,c=n.gecko,d=n.ie,u=!0,f=!1;return function(r){function p(e,t,n){var r;return e=e.toLowerCase(),(r=N.exec[e])?(r(e,t,n),u):f}function m(e){var t;return e=e.toLowerCase(),(t=N.state[e])?t(e):-1}function h(e){var t;return e=e.toLowerCase(),(t=N.value[e])?t(e):f}function g(e,t){t=t||"exec",i(e,function(e,n){i(n.toLowerCase().split(","),function(n){N[t][n]=e})})}function v(e,n,i){return n===t&&(n=f),i===t&&(i=null),r.getDoc().execCommand(e,n,i)}function y(e){return k.match(e)}function b(e,n){k.toggle(e,n?{value:n}:t),r.nodeChanged()}function C(e){S=_.getBookmark(e)}function x(){_.moveToBookmark(S)}var w=r.dom,_=r.selection,N={state:{},exec:{},value:{}},E=r.settings,k=r.formatter,S;o(this,{execCommand:p,queryCommandState:m,queryCommandValue:h,addCommands:g}),g({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){r.undoManager.add()},"Cut,Copy,Paste":function(e){var t=r.getDoc(),i;try{v(e)}catch(o){i=u}if(i||!t.queryCommandSupported(e)){var a=r.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.");n.mac&&(a=a.replace(/Ctrl\+/g,"\u2318+")),r.windowManager.alert(a)}},unlink:function(){if(_.isCollapsed()){var e=_.getNode();return void("A"==e.tagName&&r.dom.remove(e,!0))}k.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t=e.substring(7);"full"==t&&(t="justify"),i("left,center,right,justify".split(","),function(e){t!=e&&k.remove("align"+e)}),b("align"+t),p("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(e){var t,n;v(e),t=w.getParent(_.getNode(),"ol,ul"),t&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(C(),w.split(n,t),x()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){b(e)},"ForeColor,HiliteColor,FontName":function(e,t,n){b(e,n)},FontSize:function(e,t,n){var r,i;n>=1&&7>=n&&(i=l(E.font_size_style_values),r=l(E.font_size_classes),n=r?r[n-1]||n:i[n-1]||n),b(e,n)},RemoveFormat:function(e){k.remove(e)},mceBlockQuote:function(){b("blockquote")},FormatBlock:function(e,t,n){return b(n||"p")},mceCleanup:function(){var e=_.getBookmark();r.setContent(r.getContent({cleanup:u}),{cleanup:u}),_.moveToBookmark(e)},mceRemoveNode:function(e,t,n){var i=n||_.getNode();i!=r.getBody()&&(C(),r.dom.remove(i,u),x())},mceSelectNodeDepth:function(e,t,n){var i=0;w.getParent(_.getNode(),function(e){return 1==e.nodeType&&i++==n?(_.select(e),f):void 0},r.getBody())},mceSelectNode:function(e,t,n){_.select(n)},mceInsertContent:function(t,n,i){function o(e){function t(e){return r[e]&&3==r[e].nodeType}var n,r,i;return n=_.getRng(!0),r=n.startContainer,i=n.startOffset,3==r.nodeType&&(i>0?e=e.replace(/^ /," "):t("previousSibling")||(e=e.replace(/^ /," ")),i|)$/," "):t("nextSibling")||(e=e.replace(/( | )(
    |)$/," "))),e}var a,s,l,c,u,f,p,m,h,g,v;/^ | $/.test(i)&&(i=o(i)),a=r.parser,s=new e({},r.schema),v='ÈB;',f={content:i,format:"html",selection:!0},r.fire("BeforeSetContent",f),i=f.content,-1==i.indexOf("{$caret}")&&(i+="{$caret}"),i=i.replace(/\{\$caret\}/,v),m=_.getRng(); +var y=m.startContainer||(m.parentElement?m.parentElement():null),b=r.getBody();y===b&&_.isCollapsed()&&w.isBlock(b.firstChild)&&w.isEmpty(b.firstChild)&&(m=w.createRng(),m.setStart(b.firstChild,0),m.setEnd(b.firstChild,0),_.setRng(m)),_.isCollapsed()||r.getDoc().execCommand("Delete",!1,null),l=_.getNode();var C={context:l.nodeName.toLowerCase()};if(u=a.parse(i,C),h=u.lastChild,"mce_marker"==h.attr("id"))for(p=h,h=h.prev;h;h=h.walk(!0))if(3==h.type||!w.isBlock(h.name)){h.parent.insert(p,h,"br"===h.name);break}if(C.invalid){for(_.setContent(v),l=_.getNode(),c=r.getBody(),9==l.nodeType?l=h=c:h=l;h!==c;)l=h,h=h.parentNode;i=l==c?c.innerHTML:w.getOuterHTML(l),i=s.serialize(a.parse(i.replace(//i,function(){return s.serialize(u)}))),l==c?w.setHTML(c,i):w.setOuterHTML(l,i)}else i=s.serialize(u),h=l.firstChild,g=l.lastChild,!h||h===g&&"BR"===h.nodeName?w.setHTML(l,i):_.setContent(i);p=w.get("mce_marker"),_.scrollIntoView(p),m=w.createRng(),h=p.previousSibling,h&&3==h.nodeType?(m.setStart(h,h.nodeValue.length),d||(g=p.nextSibling,g&&3==g.nodeType&&(h.appendData(g.data),g.parentNode.removeChild(g)))):(m.setStartBefore(p),m.setEndBefore(p)),w.remove(p),_.setRng(m),r.fire("SetContent",f),r.addVisual()},mceInsertRawHTML:function(e,t,n){_.setContent("tiny_mce_marker"),r.setContent(r.getContent().replace(/tiny_mce_marker/g,function(){return n}))},mceToggleFormat:function(e,t,n){b(n)},mceSetContent:function(e,t,n){r.setContent(n)},"Indent,Outdent":function(e){var t,n,o;t=E.indentation,n=/[a-z%]+$/i.exec(t),t=parseInt(t,10),m("InsertUnorderedList")||m("InsertOrderedList")?v(e):(E.forced_root_block||w.getParent(_.getNode(),w.isBlock)||k.apply("div"),i(_.getSelectedBlocks(),function(i){if("LI"!=i.nodeName){var a=r.getParam("indent_use_margin",!1)?"margin":"padding";a+="rtl"==w.getStyle(i,"direction",!0)?"Right":"Left","outdent"==e?(o=Math.max(0,parseInt(i.style[a]||0,10)-t),w.setStyle(i,a,o?o+n:"")):(o=parseInt(i.style[a]||0,10)+t+n,w.setStyle(i,a,o))}}))},mceRepaint:function(){if(c)try{C(u),_.getSel()&&_.getSel().selectAllChildren(r.getBody()),_.collapse(u),x()}catch(e){}},InsertHorizontalRule:function(){r.execCommand("mceInsertContent",!1,"


    ")},mceToggleVisualAid:function(){r.hasVisual=!r.hasVisual,r.addVisual()},mceReplaceContent:function(e,t,n){r.execCommand("mceInsertContent",!1,n.replace(/\{\$selection\}/g,_.getContent({format:"text"})))},mceInsertLink:function(e,t,n){var r;"string"==typeof n&&(n={href:n}),r=w.getParent(_.getNode(),"a"),n.href=n.href.replace(" ","%20"),r&&n.href||k.remove("link"),n.href&&k.apply("link",n,r)},selectAll:function(){var e=w.getRoot(),t;_.getRng().setStart?(t=w.createRng(),t.setStart(e,0),t.setEnd(e,e.childNodes.length),_.setRng(t)):(t=_.getRng(),t.item||(t.moveToElementText(e),t.select()))},"delete":function(){v("Delete");var e=r.getBody();w.isEmpty(e)&&(r.setContent(""),e.firstChild&&w.isBlock(e.firstChild)?r.selection.setCursorLocation(e.firstChild,0):r.selection.setCursorLocation(e,0))},mceNewDocument:function(){r.setContent("")}}),g({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t="align"+e.substring(7),n=_.isCollapsed()?[w.getParent(_.getNode(),w.isBlock)]:_.getSelectedBlocks(),r=a(n,function(e){return!!k.matchNode(e,t)});return-1!==s(r,u)},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return y(e)},mceBlockQuote:function(){return y("blockquote")},Outdent:function(){var e;if(E.inline_styles){if((e=w.getParent(_.getStart(),w.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return u;if((e=w.getParent(_.getEnd(),w.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return u}return m("InsertUnorderedList")||m("InsertOrderedList")||!E.inline_styles&&!!w.getParent(_.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(e){var t=w.getParent(_.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),g({"FontSize,FontName":function(e){var t=0,n;return(n=w.getParent(_.getNode(),"span"))&&(t="fontsize"==e?n.style.fontSize:n.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()),t}},"value"),g({Undo:function(){r.undoManager.undo()},Redo:function(){r.undoManager.redo()}})}}),r(O,[f],function(e){function t(e,i){var o=this,a,s;if(e=r(e),i=o.settings=i||{},/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e))return void(o.source=e);var l=0===e.indexOf("//");0!==e.indexOf("/")||l||(e=(i.base_uri?i.base_uri.protocol||"http":"http")+"://mce_host"+e),/^[\w\-]*:?\/\//.test(e)||(s=i.base_uri?i.base_uri.path:new t(location.href).directory,e=""===i.base_uri.protocol?"//mce_host"+o.toAbsPath(s,e):(i.base_uri&&i.base_uri.protocol||"http")+"://mce_host"+o.toAbsPath(s,e)),e=e.replace(/@@/g,"(mce_at)"),e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e),n(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(t,n){var r=e[n];r&&(r=r.replace(/\(mce_at\)/g,"@@")),o[t]=r}),a=i.base_uri,a&&(o.protocol||(o.protocol=a.protocol),o.userInfo||(o.userInfo=a.userInfo),o.port||"mce_host"!==o.host||(o.port=a.port),o.host&&"mce_host"!==o.host||(o.host=a.host),o.source=""),l&&(o.protocol="")}var n=e.each,r=e.trim;return t.prototype={setPath:function(e){var t=this;e=/^(.*?)\/?(\w+)?$/.exec(e),t.path=e[0],t.directory=e[1],t.file=e[2],t.source="",t.getURI()},toRelative:function(e){var n=this,r;if("./"===e)return e;if(e=new t(e,{base_uri:n}),"mce_host"!=e.host&&n.host!=e.host&&e.host||n.port!=e.port||n.protocol!=e.protocol&&""!==e.protocol)return e.getURI();var i=n.getURI(),o=e.getURI();return i==o||"/"==i.charAt(i.length-1)&&i.substr(0,i.length-1)==o?i:(r=n.toRelPath(n.path,e.path),e.query&&(r+="?"+e.query),e.anchor&&(r+="#"+e.anchor),r)},toAbsolute:function(e,n){return e=new t(e,{base_uri:this}),e.getURI(this.host==e.host&&this.protocol==e.protocol?n:0)},toRelPath:function(e,t){var n,r=0,i="",o,a;if(e=e.substring(0,e.lastIndexOf("/")),e=e.split("/"),n=t.split("/"),e.length>=n.length)for(o=0,a=e.length;a>o;o++)if(o>=n.length||e[o]!=n[o]){r=o+1;break}if(e.lengtho;o++)if(o>=e.length||e[o]!=n[o]){r=o+1;break}if(1===r)return t;for(o=0,a=e.length-(r-1);a>o;o++)i+="../";for(o=r-1,a=n.length;a>o;o++)i+=o!=r-1?"/"+n[o]:n[o];return i},toAbsPath:function(e,t){var r,i=0,o=[],a,s;for(a=/\/$/.test(t)?"/":"",e=e.split("/"),t=t.split("/"),n(e,function(e){e&&o.push(e)}),e=o,r=t.length-1,o=[];r>=0;r--)0!==t[r].length&&"."!==t[r]&&(".."!==t[r]?i>0?i--:o.push(t[r]):i++);return r=e.length-i,s=0>=r?o.reverse().join("/"):e.slice(0,r).join("/")+"/"+o.reverse().join("/"),0!==s.indexOf("/")&&(s="/"+s),a&&s.lastIndexOf("/")!==s.length-1&&(s+=a),s},getURI:function(e){var t,n=this;return(!n.source||e)&&(t="",e||(t+=n.protocol?n.protocol+"://":"//",n.userInfo&&(t+=n.userInfo+"@"),n.host&&(t+=n.host),n.port&&(t+=":"+n.port)),n.path&&(t+=n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),n.source=t),n.source}},t}),r(I,[f],function(e){function t(){}var n=e.each,r=e.extend,i,o;return t.extend=i=function(e){function t(){var e,t,n,r;if(!o&&(r=this,r.init&&r.init.apply(r,arguments),t=r.Mixins))for(e=t.length;e--;)n=t[e],n.init&&n.init.apply(r,arguments)}function a(){return this}function s(e,t){return function(){var n=this,r=n._super,i;return n._super=c[e],i=t.apply(n,arguments),n._super=r,i}}var l=this,c=l.prototype,d,u,f;o=!0,d=new l,o=!1,e.Mixins&&(n(e.Mixins,function(t){t=t;for(var n in t)"init"!==n&&(e[n]=t[n])}),c.Mixins&&(e.Mixins=c.Mixins.concat(e.Mixins))),e.Methods&&n(e.Methods.split(","),function(t){e[t]=a}),e.Properties&&n(e.Properties.split(","),function(t){var n="_"+t;e[t]=function(e){var t=this,r;return e!==r?(t[n]=e,t):t[n]}}),e.Statics&&n(e.Statics,function(e,n){t[n]=e}),e.Defaults&&c.Defaults&&(e.Defaults=r({},c.Defaults,e.Defaults));for(u in e)f=e[u],d[u]="function"==typeof f&&c[u]?s(u,f):f;return t.prototype=d,t.constructor=t,t.extend=i,t},t}),r(z,[I],function(e){function t(e){for(var t=[],n=e.length,r;n--;)r=e[n],r.__checked||(t.push(r),r.__checked=1);for(n=t.length;n--;)delete t[n].__checked;return t}var n=/^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i,r=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i=/^\s*|\s*$/g,o,a=e.extend({init:function(e){function t(e){return e?(e=e.toLowerCase(),function(t){return"*"===e||t.type===e}):void 0}function o(e){return e?function(t){return t._name===e}:void 0}function a(e){return e?(e=e.split("."),function(t){for(var n=e.length;n--;)if(!t.hasClass(e[n]))return!1;return!0}):void 0}function s(e,t,n){return e?function(r){var i=r[e]?r[e]():"";return t?"="===t?i===n:"*="===t?i.indexOf(n)>=0:"~="===t?(" "+i+" ").indexOf(" "+n+" ")>=0:"!="===t?i!=n:"^="===t?0===i.indexOf(n):"$="===t?i.substr(i.length-n.length)===n:!1:!!n}:void 0}function l(e){var t;return e?(e=/(?:not\((.+)\))|(.+)/i.exec(e),e[1]?(t=d(e[1],[]),function(e){return!u(e,t)}):(e=e[2],function(t,n,r){return"first"===e?0===n:"last"===e?n===r-1:"even"===e?n%2===0:"odd"===e?n%2===1:t[e]?t[e]():!1})):void 0}function c(e,r,c){function d(e){e&&r.push(e)}var u;return u=n.exec(e.replace(i,"")),d(t(u[1])),d(o(u[2])),d(a(u[3])),d(s(u[4],u[5],u[6])),d(l(u[7])),r.psuedo=!!u[7],r.direct=c,r}function d(e,t){var n=[],i,o,a;do if(r.exec(""),o=r.exec(e),o&&(e=o[3],n.push(o[1]),o[2])){i=o[3];break}while(o);for(i&&d(i,t),e=[],a=0;a"!=n[a]&&e.push(c(n[a],[],">"===n[a-1]));return t.push(e),t}var u=this.match;this._selectors=d(e,[])},match:function(e,t){var n,r,i,o,a,s,l,c,d,u,f,p,m;for(t=t||this._selectors,n=0,r=t.length;r>n;n++){for(a=t[n],o=a.length,m=e,p=0,i=o-1;i>=0;i--)for(c=a[i];m;){if(c.psuedo)for(f=m.parent().items(),d=u=f.length;d--&&f[d]!==m;);for(s=0,l=c.length;l>s;s++)if(!c[s](m,d,u)){s=l+1;break}if(s===l){p++;break}if(i===o-1)break;m=m.parent()}if(p===o)return!0}return!1},find:function(e){function n(e,t,i){var o,a,s,l,c,d=t[i];for(o=0,a=e.length;a>o;o++){for(c=e[o],s=0,l=d.length;l>s;s++)if(!d[s](c,o,a)){s=l+1;break}if(s===l)i==t.length-1?r.push(c):c.items&&n(c.items(),t,i+1);else if(d.direct)return;c.items&&n(c.items(),t,i)}}var r=[],i,s,l=this._selectors;if(e.items){for(i=0,s=l.length;s>i;i++)n(e.items(),l[i],0);s>1&&(r=t(r))}return o||(o=a.Collection),new o(r)}});return a}),r(F,[f,z,I],function(e,t,n){var r,i,o=Array.prototype.push,a=Array.prototype.slice;return i={length:0,init:function(e){e&&this.add(e)},add:function(t){var n=this;return e.isArray(t)?o.apply(n,t):t instanceof r?n.add(t.toArray()):o.call(n,t),n},set:function(e){var t=this,n=t.length,r;for(t.length=0,t.add(e),r=t.length;n>r;r++)delete t[r];return t},filter:function(e){var n=this,i,o,a=[],s,l;for("string"==typeof e?(e=new t(e),l=function(t){return e.match(t)}):l=e,i=0,o=n.length;o>i;i++)s=n[i],l(s)&&a.push(s);return new r(a)},slice:function(){return new r(a.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},each:function(t){return e.each(this,t),this},toArray:function(){return e.toArray(this)},indexOf:function(e){for(var t=this,n=t.length;n--&&t[n]!==e;);return n},reverse:function(){return new r(e.toArray(this).reverse())},hasClass:function(e){return this[0]?this[0].hasClass(e):!1},prop:function(e,t){var n=this,r,i;return t!==r?(n.each(function(n){n[e]&&n[e](t)}),n):(i=n[0],i&&i[e]?i[e]():void 0)},exec:function(t){var n=this,r=e.toArray(arguments).slice(1);return n.each(function(e){e[t]&&e[t].apply(e,r)}),n},remove:function(){for(var e=this.length;e--;)this[e].remove();return this}},e.each("fire on off show hide addClass removeClass append prepend before after reflow".split(" "),function(t){i[t]=function(){var n=e.toArray(arguments);return this.each(function(e){t in e&&e[t].apply(e,n)}),this}}),e.each("text name disabled active selected checked visible parent value data".split(" "),function(e){i[e]=function(t){return this.prop(e,t)}}),r=n.extend(i),t.Collection=r,r}),r(W,[f,v],function(e,t){return{id:function(){return t.DOM.uniqueId()},createFragment:function(e){return t.DOM.createFragment(e)},getWindowSize:function(){return t.DOM.getViewPort()},getSize:function(e){var t,n;if(e.getBoundingClientRect){var r=e.getBoundingClientRect();t=Math.max(r.width||r.right-r.left,e.offsetWidth),n=Math.max(r.height||r.bottom-r.bottom,e.offsetHeight)}else t=e.offsetWidth,n=e.offsetHeight;return{width:t,height:n}},getPos:function(e,n){return t.DOM.getPos(e,n)},getViewPort:function(e){return t.DOM.getViewPort(e)},get:function(e){return document.getElementById(e)},addClass:function(e,n){return t.DOM.addClass(e,n)},removeClass:function(e,n){return t.DOM.removeClass(e,n)},hasClass:function(e,n){return t.DOM.hasClass(e,n)},toggleClass:function(e,n,r){return t.DOM.toggleClass(e,n,r)},css:function(e,n,r){return t.DOM.setStyle(e,n,r)},on:function(e,n,r,i){return t.DOM.bind(e,n,r,i)},off:function(e,n,r){return t.DOM.unbind(e,n,r)},fire:function(e,n,r){return t.DOM.fire(e,n,r)},innerHtml:function(e,n){t.DOM.setHTML(e,n)}}}),r(V,[I,f,F,W],function(e,t,n,r){var i=t.makeMap("focusin focusout scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave wheel keydown keypress keyup contextmenu"," "),o={},a="onmousewheel"in document,s=!1,l=e.extend({Statics:{elementIdCache:o},isRtl:function(){return l.rtl},classPrefix:"mce-",init:function(e){var n=this,i,o;if(n.settings=e=t.extend({},n.Defaults,e),n._id=r.id(),n._text=n._name="",n._width=n._height=0,n._aria={role:e.role},i=e.classes)for(i=i.split(" "),i.map={},o=i.length;o--;)i.map[i[o]]=!0;n._classes=i||[],n.visible(!0),t.each("title text width height name classes visible disabled active value".split(" "),function(t){var r=e[t],i;r!==i?n[t](r):n["_"+t]===i&&(n["_"+t]=!1)}),n.on("click",function(){return n.disabled()?!1:void 0}),e.classes&&t.each(e.classes.split(" "),function(e){n.addClass(e)}),n.settings=e,n._borderBox=n.parseBox(e.border),n._paddingBox=n.parseBox(e.padding),n._marginBox=n.parseBox(e.margin),e.hidden&&n.hide()},Properties:"parent,title,text,width,height,disabled,active,name,value",Methods:"renderHtml",getContainerElm:function(){return document.body},getParentCtrl:function(e){for(var t,n=this.getRoot().controlIdLookup;e&&n&&!(t=n[e.id]);)e=e.parentNode;return t},parseBox:function(e){var t,n=10;if(e)return"number"==typeof e?(e=e||0,{top:e,left:e,bottom:e,right:e}):(e=e.split(" "),t=e.length,1===t?e[1]=e[2]=e[3]=e[0]:2===t?(e[2]=e[0],e[3]=e[1]):3===t&&(e[3]=e[1]),{top:parseInt(e[0],n)||0,right:parseInt(e[1],n)||0,bottom:parseInt(e[2],n)||0,left:parseInt(e[3],n)||0})},borderBox:function(){return this._borderBox},paddingBox:function(){return this._paddingBox},marginBox:function(){return this._marginBox},measureBox:function(e,t){function n(t){var n=document.defaultView;return n?(t=t.replace(/[A-Z]/g,function(e){return"-"+e}),n.getComputedStyle(e,null).getPropertyValue(t)):e.currentStyle[t]}function r(e){var t=parseFloat(n(e),10);return isNaN(t)?0:t}return{top:r(t+"TopWidth"),right:r(t+"RightWidth"),bottom:r(t+"BottomWidth"),left:r(t+"LeftWidth")}},initLayoutRect:function(){var e=this,t=e.settings,n,i,o=e.getEl(),a,s,l,c,d,u,f,p;n=e._borderBox=e._borderBox||e.measureBox(o,"border"),e._paddingBox=e._paddingBox||e.measureBox(o,"padding"),e._marginBox=e._marginBox||e.measureBox(o,"margin"),p=r.getSize(o),u=t.minWidth,f=t.minHeight,l=u||p.width,c=f||p.height,a=t.width,s=t.height,d=t.autoResize,d="undefined"!=typeof d?d:!a&&!s,a=a||l,s=s||c;var m=n.left+n.right,h=n.top+n.bottom,g=t.maxWidth||65535,v=t.maxHeight||65535;return e._layoutRect=i={x:t.x||0,y:t.y||0,w:a,h:s,deltaW:m,deltaH:h,contentW:a-m,contentH:s-h,innerW:a-m,innerH:s-h,startMinWidth:u||0,startMinHeight:f||0,minW:Math.min(l,g),minH:Math.min(c,v),maxW:g,maxH:v,autoResize:d,scrollW:0},e._lastLayoutRect={},i},layoutRect:function(e){var t=this,n=t._layoutRect,r,i,o,a,s,c;return n||(n=t.initLayoutRect()),e?(o=n.deltaW,a=n.deltaH,e.x!==s&&(n.x=e.x),e.y!==s&&(n.y=e.y),e.minW!==s&&(n.minW=e.minW),e.minH!==s&&(n.minH=e.minH),i=e.w,i!==s&&(i=in.maxW?n.maxW:i,n.w=i,n.innerW=i-o),i=e.h,i!==s&&(i=in.maxH?n.maxH:i,n.h=i,n.innerH=i-a),i=e.innerW,i!==s&&(i=in.maxW-o?n.maxW-o:i,n.innerW=i,n.w=i+o),i=e.innerH,i!==s&&(i=in.maxH-a?n.maxH-a:i,n.innerH=i,n.h=i+a),e.contentW!==s&&(n.contentW=e.contentW),e.contentH!==s&&(n.contentH=e.contentH),r=t._lastLayoutRect,(r.x!==n.x||r.y!==n.y||r.w!==n.w||r.h!==n.h)&&(c=l.repaintControls,c&&c.map&&!c.map[t._id]&&(c.push(t),c.map[t._id]=!0),r.x=n.x,r.y=n.y,r.w=n.w,r.h=n.h),t):n},repaint:function(){var e=this,t,n,r,i,o=0,a=0,s,l;l=document.createRange?function(e){return e}:Math.round,t=e.getEl().style,r=e._layoutRect,s=e._lastRepaintRect||{},i=e._borderBox,o=i.left+i.right,a=i.top+i.bottom,r.x!==s.x&&(t.left=l(r.x)+"px",s.x=r.x),r.y!==s.y&&(t.top=l(r.y)+"px",s.y=r.y),r.w!==s.w&&(t.width=l(r.w-o)+"px",s.w=r.w),r.h!==s.h&&(t.height=l(r.h-a)+"px",s.h=r.h),e._hasBody&&r.innerW!==s.innerW&&(n=e.getEl("body").style,n.width=l(r.innerW)+"px",s.innerW=r.innerW),e._hasBody&&r.innerH!==s.innerH&&(n=n||e.getEl("body").style,n.height=l(r.innerH)+"px",s.innerH=r.innerH),e._lastRepaintRect=s,e.fire("repaint",{},!1)},on:function(e,t){function n(e){var t,n;return function(i){return t||r.parents().each(function(r){var i=r.settings.callbacks;return i&&(t=i[e])?(n=r,!1):void 0}),t.call(n,i)}}var r=this,o,a,s,l;if(t)for("string"==typeof t&&(t=n(t)),s=e.toLowerCase().split(" "),l=s.length;l--;)e=s[l],o=r._bindings,o||(o=r._bindings={}),a=o[e],a||(a=o[e]=[]),a.push(t),i[e]&&(r._nativeEvents?r._nativeEvents[e]=!0:r._nativeEvents={name:!0},r._rendered&&r.bindPendingEvents());return r},off:function(e,t){var n=this,r,i=n._bindings,o,a,s,l;if(i)if(e)for(s=e.toLowerCase().split(" "),r=s.length;r--;){if(e=s[r],o=i[e],!e){for(a in i)i[a].length=0;return n}if(o)if(t)for(l=o.length;l--;)o[l]===t&&o.splice(l,1);else o.length=0}else n._bindings=[];return n},fire:function(e,t,n){function r(){return!1}function i(){return!0}var o=this,a,s,l,c;if(e=e.toLowerCase(),t=t||{},t.type||(t.type=e),t.control||(t.control=o),t.preventDefault||(t.preventDefault=function(){t.isDefaultPrevented=i},t.stopPropagation=function(){t.isPropagationStopped=i},t.stopImmediatePropagation=function(){t.isImmediatePropagationStopped=i},t.isDefaultPrevented=r,t.isPropagationStopped=r,t.isImmediatePropagationStopped=r),o._bindings&&(l=o._bindings[e]))for(a=0,s=l.length;s>a&&(t.isImmediatePropagationStopped()||l[a].call(o,t)!==!1);a++);if(n!==!1)for(c=o.parent();c&&!t.isPropagationStopped();)c.fire(e,t,!1),c=c.parent();return t},hasEventListeners:function(e){return e in this._bindings},parents:function(e){var t=this,r=new n;for(t=t.parent();t;t=t.parent())r.add(t);return e&&(r=r.filter(e)),r},next:function(){var e=this.parent().items();return e[e.indexOf(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},findCommonAncestor:function(e,t){for(var n;e;){for(n=t;n&&e!=n;)n=n.parent();if(e==n)break;e=e.parent()}return e},hasClass:function(e,t){var n=this._classes[t||"control"];return e=this.classPrefix+e,n&&!!n.map[e]},addClass:function(e,t){var n=this,r,i;return e=this.classPrefix+e,r=n._classes[t||"control"],r||(r=[],r.map={},n._classes[t||"control"]=r),r.map[e]||(r.map[e]=e,r.push(e),n._rendered&&(i=n.getEl(t),i&&(i.className=r.join(" ")))),n},removeClass:function(e,t){var n=this,r,i,o;if(e=this.classPrefix+e,r=n._classes[t||"control"],r&&r.map[e])for(delete r.map[e],i=r.length;i--;)r[i]===e&&r.splice(i,1);return n._rendered&&(o=n.getEl(t),o&&(o.className=r.join(" "))),n},toggleClass:function(e,t,n){var r=this;return t?r.addClass(e,n):r.removeClass(e,n),r},classes:function(e){var t=this._classes[e||"control"];return t?t.join(" "):""},innerHtml:function(e){return r.innerHtml(this.getEl(),e),this},getEl:function(e,t){var n,i=e?this._id+"-"+e:this._id;return n=o[i]=(t===!0?null:o[i])||r.get(i)},visible:function(e){var t=this,n;return"undefined"!=typeof e?(t._visible!==e&&(t._rendered&&(t.getEl().style.display=e?"":"none"),t._visible=e,n=t.parent(),n&&(n._lastRect=null),t.fire(e?"show":"hide")),t):t._visible},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,r=n.getEl();return"undefined"==typeof t?n._aria[e]:(n._aria[e]=t,n._rendered&&("label"==e&&r.setAttribute("aria-labelledby",n._id),r.setAttribute("role"==e?e:"aria-"+e,t)),n)},encode:function(e,t){return t!==!1&&l.translate&&(e=l.translate(e)),(e||"").replace(/[&<>"]/g,function(e){return"&#"+e.charCodeAt(0)+";"})},before:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t),!0),t},after:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t)),t},remove:function(){var e=this,t=e.getEl(),n=e.parent(),i,a;if(e.items){var s=e.items().toArray();for(a=s.length;a--;)s[a].remove()}n&&n.items&&(i=[],n.items().each(function(t){t!==e&&i.push(t)}),n.items().set(i),n._lastRect=null),e._eventsRoot&&e._eventsRoot==e&&r.off(t);var l=e.getRoot().controlIdLookup;if(l&&delete l[e._id],delete o[e._id],t&&t.parentNode){var c=t.getElementsByTagName("*");for(a=c.length;a--;)delete o[c[a].id];t.parentNode.removeChild(t)}return e._rendered=!1,e},renderBefore:function(e){var t=this;return e.parentNode.insertBefore(r.createFragment(t.renderHtml()),e),t.postRender(),t},renderTo:function(e){var t=this;return e=e||t.getContainerElm(),e.appendChild(r.createFragment(t.renderHtml())),t.postRender(),t},postRender:function(){var e=this,t=e.settings,n,i,o,a,s;for(a in t)0===a.indexOf("on")&&e.on(a.substr(2),t[a]);if(e._eventsRoot){for(o=e.parent();!s&&o;o=o.parent())s=o._eventsRoot;if(s)for(a in s._nativeEvents)e._nativeEvents[a]=!0}e.bindPendingEvents(),t.style&&(n=e.getEl(),n&&(n.setAttribute("style",t.style),n.style.cssText=t.style)),e._visible||r.css(e.getEl(),"display","none"),e.settings.border&&(i=e.borderBox(),r.css(e.getEl(),{"border-top-width":i.top,"border-right-width":i.right,"border-bottom-width":i.bottom,"border-left-width":i.left}));var l=e.getRoot();l.controlIdLookup||(l.controlIdLookup={}),l.controlIdLookup[e._id]=e;for(var c in e._aria)e.aria(c,e._aria[c]);e.fire("postrender",{},!1)},scrollIntoView:function(e){function t(e,t){var n,r,i=e;for(n=r=0;i&&i!=t&&i.nodeType;)n+=i.offsetLeft||0,r+=i.offsetTop||0,i=i.offsetParent;return{x:n,y:r}}var n=this.getEl(),r=n.parentNode,i,o,a,s,l,c,d=t(n,r);return i=d.x,o=d.y,a=n.offsetWidth,s=n.offsetHeight,l=r.clientWidth,c=r.clientHeight,"end"==e?(i-=l-a,o-=c-s):"center"==e&&(i-=l/2-a/2,o-=c/2-s/2),r.scrollLeft=i,r.scrollTop=o,this},bindPendingEvents:function(){function e(e){var t=o.getParentCtrl(e.target);t&&t.fire(e.type,e)}function t(){var e=u._lastHoverCtrl;e&&(e.fire("mouseleave",{target:e.getEl()}),e.parents().each(function(e){e.fire("mouseleave",{target:e.getEl()})}),u._lastHoverCtrl=null)}function n(e){var t=o.getParentCtrl(e.target),n=u._lastHoverCtrl,r=0,i,a,s;if(t!==n){if(u._lastHoverCtrl=t,a=t.parents().toArray().reverse(),a.push(t),n){for(s=n.parents().toArray().reverse(),s.push(n),r=0;r=r;i--)n=s[i],n.fire("mouseleave",{target:n.getEl()})}for(i=r;il;l++)u=d[l]._eventsRoot;for(u||(u=d[d.length-1]||o),o._eventsRoot=u,c=l,l=0;c>l;l++)d[l]._eventsRoot=u;for(p in f){if(!f)return!1;"wheel"!==p||s?("mouseenter"===p||"mouseleave"===p?u._hasMouseEnter||(r.on(u.getEl(),"mouseleave",t),r.on(u.getEl(),"mouseover",n),u._hasMouseEnter=1):u[p]||(r.on(u.getEl(),p,e),u[p]=!0),f[p]=!1):a?r.on(o.getEl(),"mousewheel",i):r.on(o.getEl(),"DOMMouseScroll",i)}}},getRoot:function(){for(var e=this,t,n=[];e;){if(e.rootControl){t=e.rootControl;break}n.push(e),t=e,e=e.parent()}t||(t=this);for(var r=n.length;r--;)n[r].rootControl=t;return t},reflow:function(){return this.repaint(),this}});return l}),r(U,[],function(){var e={},t;return{add:function(t,n){e[t.toLowerCase()]=n},has:function(t){return!!e[t.toLowerCase()]},create:function(n,r){var i,o,a;if(!t){a=tinymce.ui;for(o in a)e[o.toLowerCase()]=a[o];t=!0}if("string"==typeof n?(r=r||{},r.type=n):(r=n,n=r.type),n=n.toLowerCase(),i=e[n],!i)throw new Error("Could not find control by type: "+n);return i=new i(r),i.type=n,i}}}),r(q,[V,F,z,U,f,W],function(e,t,n,r,i,o){var a={};return e.extend({layout:"",innerClass:"container-inner",init:function(e){var n=this;n._super(e),e=n.settings,n._fixed=e.fixed,n._items=new t,n.isRtl()&&n.addClass("rtl"),n.addClass("container"),n.addClass("container-body","body"),e.containerCls&&n.addClass(e.containerCls),n._layout=r.create((e.layout||n.layout)+"layout"),n.settings.items&&n.add(n.settings.items),n._hasBody=!0},items:function(){return this._items},find:function(e){return e=a[e]=a[e]||new n(e),e.find(this)},add:function(e){var t=this;return t.items().add(t.create(e)).parent(t),t},focus:function(){var e=this;return e.keyNav?e.keyNav.focusFirst():e._super(),e},replace:function(e,t){for(var n,r=this.items(),i=r.length;i--;)if(r[i]===e){r[i]=t;break}i>=0&&(n=t.getEl(),n&&n.parentNode.removeChild(n),n=e.getEl(),n&&n.parentNode.removeChild(n)),t.parent(this)},create:function(t){var n=this,o,a=[];return i.isArray(t)||(t=[t]),i.each(t,function(t){t&&(t instanceof e||("string"==typeof t&&(t={type:t}),o=i.extend({},n.settings.defaults,t),t.type=o.type=o.type||t.type||n.settings.defaultType||(o.defaults?o.defaults.type:null),t=r.create(o)),a.push(t))}),a},renderNew:function(){var e=this;return e.items().each(function(t,n){var r,i;t.parent(e),t._rendered||(r=e.getEl("body"),i=o.createFragment(t.renderHtml()),r.hasChildNodes()&&n<=r.childNodes.length-1?r.insertBefore(i,r.childNodes[n]):r.appendChild(i),t.postRender())}),e._layout.applyClasses(e),e._lastRect=null,e},append:function(e){return this.add(e).renderNew()},prepend:function(e){var t=this;return t.items().set(t.create(e).concat(t.items().toArray())),t.renderNew()},insert:function(e,t,n){var r=this,i,o,a;return e=r.create(e),i=r.items(),!n&&t=0&&t
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "},postRender:function(){var e=this,t;return e.items().exec("postRender"),e._super(),e._layout.postRender(e),e._rendered=!0,e.settings.style&&o.css(e.getEl(),e.settings.style),e.settings.border&&(t=e.borderBox(),o.css(e.getEl(),{"border-top-width":t.top,"border-right-width":t.right,"border-bottom-width":t.bottom,"border-left-width":t.left})),e},initLayoutRect:function(){var e=this,t=e._super();return e._layout.recalc(e),t},recalc:function(){var e=this,t=e._layoutRect,n=e._lastRect;return n&&n.w==t.w&&n.h==t.h?void 0:(e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0)},reflow:function(){var t,n;if(this.visible()){for(e.repaintControls=[],e.repaintControls.map={},n=this.recalc(),t=e.repaintControls.length;t--;)e.repaintControls[t].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),e.repaintControls=[]}return this}})}),r(j,[W],function(e){function t(){var e=document,t,n,r,i,o,a,s,l,c=Math.max;return t=e.documentElement,n=e.body,r=c(t.scrollWidth,n.scrollWidth),i=c(t.clientWidth,n.clientWidth),o=c(t.offsetWidth,n.offsetWidth),a=c(t.scrollHeight,n.scrollHeight),s=c(t.clientHeight,n.clientHeight),l=c(t.offsetHeight,n.offsetHeight),{width:o>r?i:r,height:l>a?s:a}}return function(n,r){function i(){return a.getElementById(r.handle||n)}var o,a=document,s,l,c,d,u,f;r=r||{},l=function(n){var l=t(),p,m;n.preventDefault(),s=n.button,p=i(),u=n.screenX,f=n.screenY,m=window.getComputedStyle?window.getComputedStyle(p,null).getPropertyValue("cursor"):p.runtimeStyle.cursor,o=a.createElement("div"),e.css(o,{position:"absolute",top:0,left:0,width:l.width,height:l.height,zIndex:2147483647,opacity:1e-4,background:"red",cursor:m}),a.body.appendChild(o),e.on(a,"mousemove",d),e.on(a,"mouseup",c),r.start(n)},d=function(e){return e.button!==s?c(e):(e.deltaX=e.screenX-u,e.deltaY=e.screenY-f,e.preventDefault(),void r.drag(e))},c=function(t){e.off(a,"mousemove",d),e.off(a,"mouseup",c),o.parentNode.removeChild(o),r.stop&&r.stop(t)},this.destroy=function(){e.off(i())},e.on(i(),"mousedown",l)}}),r($,[W,j],function(e,t){return{init:function(){var e=this;e.on("repaint",e.renderScroll)},renderScroll:function(){function n(){function t(t,a,s,l,c,d){var u,f,p,m,h,g,v,y,b;if(f=i.getEl("scroll"+t)){if(y=a.toLowerCase(),b=s.toLowerCase(),i.getEl("absend")&&e.css(i.getEl("absend"),y,i.layoutRect()[l]-1),!c)return void e.css(f,"display","none");e.css(f,"display","block"),u=i.getEl("body"),p=i.getEl("scroll"+t+"t"),m=u["client"+s]-2*o,m-=n&&r?f["client"+d]:0,h=u["scroll"+s],g=m/h,v={},v[y]=u["offset"+a]+o,v[b]=m,e.css(f,v),v={},v[y]=u["scroll"+a]*g,v[b]=m*g,e.css(p,v)}}var n,r,a;a=i.getEl("body"),n=a.scrollWidth>a.clientWidth,r=a.scrollHeight>a.clientHeight,t("h","Left","Width","contentW",n,"Height"),t("v","Top","Height","contentH",r,"Width")}function r(){function n(n,r,a,s,l){var c,d=i._id+"-scroll"+n,u=i.classPrefix;i.getEl().appendChild(e.createFragment('
    ')),i.draghelper=new t(d+"t",{start:function(){c=i.getEl("body")["scroll"+r],e.addClass(e.get(d),u+"active")},drag:function(e){var t,d,u,f,p=i.layoutRect();d=p.contentW>p.innerW,u=p.contentH>p.innerH,f=i.getEl("body")["client"+a]-2*o,f-=d&&u?i.getEl("scroll"+n)["client"+l]:0,t=f/i.getEl("body")["scroll"+a],i.getEl("body")["scroll"+r]=c+e["delta"+s]/t},stop:function(){e.removeClass(e.get(d),u+"active")}})}i.addClass("scroll"),n("v","Top","Height","Y","Width"),n("h","Left","Width","X","Height")}var i=this,o=2;i.settings.autoScroll&&(i._hasScroll||(i._hasScroll=!0,r(),i.on("wheel",function(e){var t=i.getEl("body");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),e.on(i.getEl("body"),"scroll",n)),n())}}}),r(K,[q,$],function(e,t){return e.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[t],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),"undefined"==typeof n?n='
    '+t.renderHtml(e)+"
    ":("function"==typeof n&&(n=n.call(e)),e._hasBody=!1),'
    '+(e._preBodyHtml||"")+n+"
    "}})}),r(Y,[W],function(e){function t(t,n,r){var i,o,a,s,l,c,d,u,f,p;return f=e.getViewPort(),o=e.getPos(n),a=o.x,s=o.y,t._fixed&&(a-=f.x,s-=f.y),i=t.getEl(),p=e.getSize(i),l=p.width,c=p.height,p=e.getSize(n),d=p.width,u=p.height,r=(r||"").split(""),"b"===r[0]&&(s+=u),"r"===r[1]&&(a+=d),"c"===r[0]&&(s+=Math.round(u/2)),"c"===r[1]&&(a+=Math.round(d/2)),"b"===r[3]&&(s-=c),"r"===r[4]&&(a-=l),"c"===r[3]&&(s-=Math.round(c/2)),"c"===r[4]&&(a-=Math.round(l/2)),{x:a,y:s,w:l,h:c}}return{testMoveRel:function(n,r){for(var i=e.getViewPort(),o=0;o0&&a.x+a.w0&&a.y+a.hi.x&&a.x+a.wi.y&&a.y+a.he?0:e+n>t?(e=t-n,0>e?0:e):e}var i=this;if(i.settings.constrainToViewport){var o=e.getViewPort(window),a=i.layoutRect();t=r(t,o.w+o.x,a.w),n=r(n,o.h+o.y,a.h)}return i._rendered?i.layoutRect({x:t,y:n}).repaint():(i.settings.x=t,i.settings.y=n),i.fire("move",{x:t,y:n}),i}}}),r(G,[W],function(e){return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(t,n){if(1>=t||1>=n){var r=e.getWindowSize();t=1>=t?t*r.w:t,n=1>=n?n*r.h:n}return this._layoutRect.autoResize=!1,this.layoutRect({minW:t,minH:n,w:t,h:n}).reflow()},resizeBy:function(e,t){var n=this,r=n.layoutRect();return n.resizeTo(r.w+e,r.h+t)}}}),r(X,[K,Y,G,W],function(e,t,n,r){function i(e){var t;for(t=s.length;t--;)s[t]===e&&s.splice(t,1);for(t=l.length;t--;)l[t]===e&&l.splice(t,1)}var o,a,s=[],l=[],c,d=e.extend({Mixins:[t,n],init:function(e){function t(){var e,t=d.zIndex||65535,n;if(l.length)for(e=0;en&&(e.fixed(!1).layoutRect({y:e._autoFixY}).repaint(),t(!1,e._autoFixY-n)):(e._autoFixY=e.layoutRect().y,e._autoFixY
    '),n=n.firstChild,u.getContainerElm().appendChild(n),setTimeout(function(){r.addClass(n,i+"in"),r.addClass(u.getEl(),i+"in")},0),c=!0),l.push(u),t()}}),u.on("close hide",function(e){if(e.control==u){for(var n=l.length;n--;)l[n]===u&&l.splice(n,1);t()}}),u.on("show",function(){u.parents().each(function(e){return e._fixed?(u.fixed(!0),!1):void 0})}),e.popover&&(u._preBodyHtml='
    ',u.addClass("popover").addClass("bottom").addClass(u.isRtl()?"end":"start"))},fixed:function(e){var t=this;if(t._fixed!=e){if(t._rendered){var n=r.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.toggleClass("fixed",e),t._fixed=e}return t},show:function(){var e=this,t,n=e._super();for(t=s.length;t--&&s[t]!==e;);return-1===t&&s.push(e),n},hide:function(){return i(this),this._super()},hideAll:function(){d.hideAll()},close:function(){var e=this;return e.fire("close"),e.remove()},remove:function(){i(this),this._super()}});return d.hideAll=function(){for(var e=s.length;e--;){var t=s[e];t.settings.autohide&&(t.fire("cancel",{},!1),t.hide(),s.splice(e,1))}},d}),r(J,[W],function(e){return function(t){function n(){if(!m)if(m=[],u.find)u.find("*").each(function(e){e.canFocus&&m.push(e.getEl())});else for(var e=u.getEl().getElementsByTagName("*"),t=0;ti?i=l.length-1:i>=l.length&&(i=0),o=l[i],o.focus(),h=o.id,t.actOnFocus&&s()}function d(){var e,r;for(r=i(t.root.getEl()),n(),e=m.length;e--;)if("toolbar"==r&&m[e].id===h)return void m[e].focus();m[0].focus()}var u=t.root,f=t.enableUpDown!==!1,p=t.enableLeftRight!==!1,m=t.items,h;return u.on("keydown",function(e){var n=37,r=39,d=38,u=40,m=27,h=14,g=13,v=32,y=9,b;switch(e.keyCode){case n:p&&(t.leftAction?t.leftAction():c(-1),b=!0);break;case r:p&&("menuitem"==i()&&"menu"==o()?a("haspopup")&&s():c(1),b=!0);break;case d:f&&(c(-1),b=!0);break;case u:f&&("menuitem"==i()&&"menubar"==o()?s():"button"==i()&&a("haspopup")?s():c(1),b=!0);break;case y:b=!0,c(e.shiftKey?-1:1);break;case m:b=!0,l();break;case h:case g:case v:b=s()}b&&(e.stopPropagation(),e.preventDefault())}),u.on("focusin",function(e){n(),h=e.target.id}),{moveFocus:c,focusFirst:d,cancel:l}}}),r(Q,[X,K,W,J,j],function(e,t,n,r,i){var o=e.extend({modal:!0,Defaults:{border:1,layout:"flex",containerCls:"panel",role:"dialog",callbacks:{submit:function(){this.fire("submit",{data:this.toJSON()})},close:function(){this.close()}}},init:function(e){var n=this;n._super(e),n.isRtl()&&n.addClass("rtl"),n.addClass("window"),n._fixed=!0,e.buttons&&(n.statusbar=new t({layout:"flex",border:"1 0 0 0",spacing:3,padding:10,align:"center",pack:n.isRtl()?"start":"end",defaults:{type:"button"},items:e.buttons}),n.statusbar.addClass("foot"),n.statusbar.parent(n)),n.on("click",function(e){-1!=e.target.className.indexOf(n.classPrefix+"close")&&n.close()}),n.aria("label",e.title),n._fullscreen=!1},recalc:function(){var e=this,t=e.statusbar,r,i,o,a;e._fullscreen&&(e.layoutRect(n.getWindowSize()),e.layoutRect().contentH=e.layoutRect().innerH),e._super(),r=e.layoutRect(),e.settings.title&&!e._fullscreen&&(i=r.headerW,i>r.w&&(o=r.x-Math.max(0,i/2),e.layoutRect({w:i,x:o}),a=!0)),t&&(t.layoutRect({w:e.layoutRect().innerW}).recalc(),i=t.layoutRect().minW+r.deltaW,i>r.w&&(o=r.x-Math.max(0,i-r.w),e.layoutRect({w:i,x:o}),a=!0)),a&&e.recalc()},initLayoutRect:function(){var e=this,t=e._super(),r=0,i;if(e.settings.title&&!e._fullscreen){i=e.getEl("head");var o=n.getSize(i);t.headerW=o.width,t.headerH=o.height,r+=t.headerH}e.statusbar&&(r+=e.statusbar.layoutRect().h),t.deltaH+=r,t.minH+=r,t.h+=r;var a=n.getWindowSize();return t.x=Math.max(0,a.w/2-t.w/2),t.y=Math.max(0,a.h/2-t.h/2),t},renderHtml:function(){var e=this,t=e._layout,n=e._id,r=e.classPrefix,i=e.settings,o="",a="",s=i.html;return e.preRender(),t.preRender(e),i.title&&(o='
    '+e.encode(i.title)+'
    '),i.url&&(s=''),"undefined"==typeof s&&(s=t.renderHtml(e)),e.statusbar&&(a=e.statusbar.renderHtml()),'
    '+o+'
    '+s+"
    "+a+"
    "},fullscreen:function(e){var t=this,r=document.documentElement,i,o=t.classPrefix,a;if(e!=t._fullscreen)if(n.on(window,"resize",function(){var e;if(t._fullscreen)if(i)t._timer||(t._timer=setTimeout(function(){var e=n.getWindowSize();t.moveTo(0,0).resizeTo(e.w,e.h),t._timer=0},50));else{e=(new Date).getTime();var r=n.getWindowSize();t.moveTo(0,0).resizeTo(r.w,r.h),(new Date).getTime()-e>50&&(i=!0)}}),a=t.layoutRect(),t._fullscreen=e,e){t._initial={x:a.x,y:a.y,w:a.w,h:a.h},t._borderBox=t.parseBox("0"),t.getEl("head").style.display="none",a.deltaH-=a.headerH+2,n.addClass(r,o+"fullscreen"),n.addClass(document.body,o+"fullscreen"),t.addClass("fullscreen");var s=n.getWindowSize();t.moveTo(0,0).resizeTo(s.w,s.h)}else t._borderBox=t.parseBox(t.settings.border),t.getEl("head").style.display="",a.deltaH+=a.headerH,n.removeClass(r,o+"fullscreen"),n.removeClass(document.body,o+"fullscreen"),t.removeClass("fullscreen"),t.moveTo(t._initial.x,t._initial.y).resizeTo(t._initial.w,t._initial.h);return t.reflow()},postRender:function(){var e=this,t=[],n,o,a;setTimeout(function(){e.addClass("in")},0),e.keyboardNavigation=new r({root:e,enableLeftRight:!1,enableUpDown:!1,items:t,onCancel:function(){e.close()}}),e.find("*").each(function(e){e.canFocus&&(o=o||e.settings.autofocus,n=n||e,e.subinput?(t.push(e.getEl("inp")),e.getEl("open")&&t.push(e.getEl("open"))):t.push(e.getEl()))}),e.statusbar&&e.statusbar.find("*").each(function(e){e.canFocus&&(o=o||e.settings.autofocus,n=n||e,t.push(e.getEl()))}),e._super(),e.statusbar&&e.statusbar.postRender(),!o&&n&&n.focus(),this.dragHelper=new i(e._id+"-dragh",{start:function(){a={x:e.layoutRect().x,y:e.layoutRect().y}},drag:function(t){e.moveTo(a.x+t.deltaX,a.y+t.deltaY)}}),e.on("submit",function(t){t.isDefaultPrevented()||e.close()})},submit:function(){return this.fire("submit",{data:this.toJSON()})},remove:function(){var e=this,t=e.classPrefix;e.dragHelper.destroy(),e._super(),e.statusbar&&this.statusbar.remove(),e._fullscreen&&(n.removeClass(document.documentElement,t+"fullscreen"),n.removeClass(document.body,t+"fullscreen"))}});return o}),r(Z,[Q],function(e){var t=e.extend({init:function(e){e={border:1,padding:20,layout:"flex",pack:"center",align:"center",containerCls:"panel",autoScroll:!0,buttons:{type:"button",text:"Ok",action:"ok"},items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200}},this._super(e)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(n){var r,i=n.callback||function(){};switch(n.buttons){case t.OK_CANCEL:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}},{type:"button",text:"Cancel",onClick:function(e){e.control.parents()[1].close(),i(!1)}}];break;case t.YES_NO:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}}];break;case t.YES_NO_CANCEL:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close()}}];break;default:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}}]}return new e({padding:20,x:n.x,y:n.y,minWidth:300,minHeight:100,layout:"flex",pack:"center",align:"center",buttons:r,title:n.title,items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200,text:n.text},onClose:n.onClose}).renderTo(document.body).reflow()},alert:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,t.msgBox(e)},confirm:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,e.buttons=t.OK_CANCEL,t.msgBox(e)}}});return t}),r(et,[Q,Z],function(e,t){return function(n){function r(){return o.length?o[o.length-1]:void 0}var i=this,o=[];i.windows=o,i.open=function(t,r){var i;return n.editorManager.activeEditor=n,t.title=t.title||" ",t.url=t.url||t.file,t.url&&(t.width=parseInt(t.width||320,10),t.height=parseInt(t.height||240,10)),t.body&&(t.items={defaults:t.defaults,type:t.bodyType||"form",items:t.body}),t.url||t.buttons||(t.buttons=[{text:"Ok",subtype:"primary",onclick:function(){i.find("form")[0].submit(),i.close()}},{text:"Cancel",onclick:function(){i.close()}}]),i=new e(t),o.push(i),i.on("close",function(){for(var e=o.length;e--;)o[e]===i&&o.splice(e,1);n.focus()}),t.data&&i.on("postRender",function(){this.find("*").each(function(e){var n=e.name();n in t.data&&e.value(t.data[n])})}),i.features=t||{},i.params=r||{},n.nodeChanged(),i.renderTo(document.body).reflow()},i.alert=function(e,n,r){t.alert(e,function(){n&&n.call(r||this)})},i.confirm=function(e,n,r){t.confirm(e,function(e){n.call(r||this,e)})},i.close=function(){r()&&r().close()},i.getParams=function(){return r()?r().params:null},i.setParams=function(e){r()&&(r().params=e)}}}),r(tt,[T,B,C,m,h,f],function(e,t,n,r,i,o){return function(a){function s(e,t){try{a.getDoc().execCommand(e,!1,t)}catch(n){}}function l(){var e=a.getDoc().documentMode;return e?e:6}function c(e){return e.isDefaultPrevented()}function d(){function t(e){var t=new MutationObserver(function(){});o.each(a.getBody().getElementsByTagName("*"),function(e){"SPAN"==e.tagName&&e.setAttribute("mce-data-marked",1),!e.hasAttribute("data-mce-style")&&e.hasAttribute("style")&&a.dom.setAttrib(e,"style",e.getAttribute("style"))}),t.observe(a.getDoc(),{childList:!0,attributes:!0,subtree:!0,attributeFilter:["style"]}),a.getDoc().execCommand(e?"ForwardDelete":"Delete",!1,null);var n=a.selection.getRng(),r=n.startContainer.parentNode;o.each(t.takeRecords(),function(e){if("style"==e.attributeName){var t=e.target.getAttribute("data-mce-style");t?e.target.setAttribute("style",t):e.target.removeAttribute("style")}o.each(e.addedNodes,function(e){if("SPAN"==e.nodeName&&!e.getAttribute("mce-data-marked")){var t,i;e==r&&(t=n.startOffset,i=e.firstChild),W.remove(e,!0),i&&(n.setStart(i,t),n.setEnd(i,t),a.selection.setRng(n))}})}),t.disconnect(),o.each(a.dom.select("span[mce-data-marked]"),function(e){e.removeAttribute("mce-data-marked")})}var n=a.getDoc();window.MutationObserver&&(a.on("keydown",function(n){var r=n.keyCode==F,i=e.metaKeyPressed(n);if(!c(n)&&(r||n.keyCode==z)){var o=a.selection.getRng(),s=o.startContainer,l=o.startOffset;if(!i&&o.collapsed&&3==s.nodeType&&(r?l0))return;n.preventDefault(),i&&a.selection.getSel().modify("extend",r?"forward":"backward","word"),t(r)}}),a.on("keypress",function(n){c(n)||V.isCollapsed()||!n.charCode||e.metaKeyPressed(n)||(n.preventDefault(),t(!0),a.selection.setContent(String.fromCharCode(n.charCode)))}),a.addCommand("Delete",function(){t()}),a.addCommand("ForwardDelete",function(){t(!0)}),a.on("dragstart",function(e){e.dataTransfer.setData("mce-internal",a.selection.getContent())}),a.on("drop",function(e){if(!c(e)){var r=e.dataTransfer.getData("mce-internal");r&&n.caretRangeFromPoint&&(e.preventDefault(),t(),a.selection.setRng(n.caretRangeFromPoint(e.x,e.y)),a.insertContent(r))}}),a.on("cut",function(e){!c(e)&&e.clipboardData&&(e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/html",a.selection.getContent()),e.clipboardData.setData("text/plain",a.selection.getContent({format:"text"})),t(!0))}))}function u(){function e(e){var t=W.create("body"),n=e.cloneContents();return t.appendChild(n),V.serializer.serialize(t,{format:"html"})}function n(n){if(!n.setStart){if(n.item)return!1;var r=n.duplicate();return r.moveToElementText(a.getBody()),t.compareRanges(n,r)}var i=e(n),o=W.createRng();o.selectNode(a.getBody());var s=e(o);return i===s}a.on("keydown",function(e){var t=e.keyCode,r,i;if(!c(e)&&(t==F||t==z)){if(r=a.selection.isCollapsed(),i=a.getBody(),r&&!W.isEmpty(i))return;if(!r&&!n(a.selection.getRng()))return;e.preventDefault(),a.setContent(""),i.firstChild&&W.isBlock(i.firstChild)?a.selection.setCursorLocation(i.firstChild,0):a.selection.setCursorLocation(i,0),a.nodeChanged()}})}function f(){a.on("keydown",function(t){!c(t)&&65==t.keyCode&&e.metaKeyPressed(t)&&(t.preventDefault(),a.execCommand("SelectAll"))})}function p(){a.settings.content_editable||(W.bind(a.getDoc(),"focusin",function(){V.setRng(V.getRng())}),W.bind(a.getDoc(),"mousedown",function(e){e.target==a.getDoc().documentElement&&(a.getBody().focus(),V.setRng(V.getRng()))}))}function m(){a.on("keydown",function(e){if(!c(e)&&e.keyCode===z&&V.isCollapsed()&&0===V.getRng(!0).startOffset){var t=V.getNode(),n=t.previousSibling;if("HR"==t.nodeName)return W.remove(t),void e.preventDefault();n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(W.remove(n),e.preventDefault())}})}function h(){window.Range.prototype.getClientRects||a.on("mousedown",function(e){if(!c(e)&&"HTML"===e.target.nodeName){var t=a.getBody();t.blur(),setTimeout(function(){t.focus()},0)}})}function g(){a.on("click",function(e){e=e.target,/^(IMG|HR)$/.test(e.nodeName)&&V.getSel().setBaseAndExtent(e,0,e,1),"A"==e.nodeName&&W.hasClass(e,"mce-item-anchor")&&V.select(e),a.nodeChanged()})}function v(){function e(){var e=W.getAttribs(V.getStart().cloneNode(!1));return function(){var t=V.getStart();t!==a.getBody()&&(W.setAttrib(t,"style",null),I(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function t(){return!V.isCollapsed()&&W.getParent(V.getStart(),W.isBlock)!=W.getParent(V.getEnd(),W.isBlock)}a.on("keypress",function(n){var r;return c(n)||8!=n.keyCode&&46!=n.keyCode||!t()?void 0:(r=e(),a.getDoc().execCommand("delete",!1,null),r(),n.preventDefault(),!1)}),W.bind(a.getDoc(),"cut",function(n){var r;!c(n)&&t()&&(r=e(),setTimeout(function(){r()},0))})}function y(){var e,n;a.on("selectionchange",function(){n&&(clearTimeout(n),n=0),n=window.setTimeout(function(){var n=V.getRng();e&&t.compareRanges(n,e)||(a.nodeChanged(),e=n)},50)})}function b(){document.body.setAttribute("role","application")}function C(){a.on("keydown",function(e){if(!c(e)&&e.keyCode===z&&V.isCollapsed()&&0===V.getRng(!0).startOffset){var t=V.getNode().previousSibling;if(t&&t.nodeName&&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function x(){l()>7||(s("RespectVisibilityInDesign",!0),a.contentStyles.push(".mceHideBrInPre pre br {display: none}"),W.addClass(a.getBody(),"mceHideBrInPre"),q.addNodeFilter("pre",function(e){for(var t=e.length,r,i,o,a;t--;)for(r=e[t].getAll("br"),i=r.length;i--;)o=r[i],a=o.prev,a&&3===a.type&&"\n"!=a.value.charAt(a.value-1)?a.value+="\n":o.parent.insert(new n("#text",3),o,!0).value="\n"}),j.addNodeFilter("pre",function(e){for(var t=e.length,n,r,i,o;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)i=n[r],o=i.prev,o&&3==o.type&&(o.value=o.value.replace(/\r?\n$/,""))}))}function w(){W.bind(a.getBody(),"mouseup",function(){var e,t=V.getNode();"IMG"==t.nodeName&&((e=W.getStyle(t,"width"))&&(W.setAttrib(t,"width",e.replace(/[^0-9%]+/g,"")),W.setStyle(t,"width","")),(e=W.getStyle(t,"height"))&&(W.setAttrib(t,"height",e.replace(/[^0-9%]+/g,"")),W.setStyle(t,"height","")))})}function _(){a.on("keydown",function(t){var n,r,i,o,s;if(!c(t)&&t.keyCode==e.BACKSPACE&&(n=V.getRng(),r=n.startContainer,i=n.startOffset,o=W.getRoot(),s=r,n.collapsed&&0===i)){for(;s&&s.parentNode&&s.parentNode.firstChild==s&&s.parentNode!=o;)s=s.parentNode;"BLOCKQUOTE"===s.tagName&&(a.formatter.toggle("blockquote",null,s),n=W.createRng(),n.setStart(r,0),n.setEnd(r,0),V.setRng(n))}})}function N(){function e(){a._refreshContentEditable(),s("StyleWithCSS",!1),s("enableInlineTableEditing",!1),U.object_resizing||s("enableObjectResizing",!1)}U.readonly||a.on("BeforeExecCommand MouseDown",e)}function E(){function e(){I(W.select("a"),function(e){var t=e.parentNode,n=W.getRoot();if(t.lastChild===e){for(;t&&!W.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}W.add(t,"br",{"data-mce-bogus":1})}})}a.on("SetContent ExecCommand",function(t){("setcontent"==t.type||"mceInsertLink"===t.command)&&e()})}function k(){U.forced_root_block&&a.on("init",function(){s("DefaultParagraphSeparator",U.forced_root_block)})}function S(){a.on("Undo Redo SetContent",function(e){e.initial||a.execCommand("mceRepaint")})}function T(){a.on("keydown",function(e){var t;c(e)||e.keyCode!=z||(t=a.getDoc().selection.createRange(),t&&t.item&&(e.preventDefault(),a.undoManager.beforeChange(),W.remove(t.item(0)),a.undoManager.add()))})}function R(){var e;l()>=10&&(e="",I("p div h1 h2 h3 h4 h5 h6".split(" "),function(t,n){e+=(n>0?",":"")+t+":empty"}),a.contentStyles.push(e+"{padding-right: 1px !important}"))}function A(){l()<9&&(q.addNodeFilter("noscript",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.firstChild,r&&n.attr("data-mce-innertext",r.value)}),j.addNodeFilter("noscript",function(e){for(var t=e.length,i,o,a;t--;)i=e[t],o=e[t].firstChild,o?o.value=r.decode(o.value):(a=i.attributes.map["data-mce-innertext"],a&&(i.attr("data-mce-innertext",null),o=new n("#text",3),o.value=a,o.raw=!0,i.append(o)))}))}function B(){function e(e,t){var n=i.createTextRange();try{n.moveToPoint(e,t)}catch(r){n=null}return n}function t(t){var r;t.button?(r=e(t.x,t.y),r&&(r.compareEndPoints("StartToStart",a)>0?r.setEndPoint("StartToStart",a):r.setEndPoint("EndToEnd",a),r.select())):n()}function n(){var e=r.selection.createRange();a&&!e.item&&0===e.compareEndPoints("StartToEnd",e)&&a.select(),W.unbind(r,"mouseup",n),W.unbind(r,"mousemove",t),a=o=0}var r=W.doc,i=r.body,o,a,s;r.documentElement.unselectable=!0,W.bind(r,"mousedown contextmenu",function(i){if("HTML"===i.target.nodeName){if(o&&n(),s=r.documentElement,s.scrollHeight>s.clientHeight)return;o=1,a=e(i.x,i.y),a&&(W.bind(r,"mouseup",n),W.bind(r,"mousemove",t),W.win.focus(),a.select())}})}function L(){a.on("keyup focusin",function(t){65==t.keyCode&&e.metaKeyPressed(t)||V.normalize()})}function H(){a.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}function M(){a.inline||a.on("keydown",function(){document.activeElement==document.body&&a.getWin().focus()})}function D(){a.inline||(a.contentStyles.push("body {min-height: 150px}"),a.on("click",function(e){"HTML"==e.target.nodeName&&(a.execCommand("SelectAll"),a.selection.collapse(!0),a.nodeChanged())}))}function P(){i.mac&&a.on("keydown",function(t){!e.metaKeyPressed(t)||37!=t.keyCode&&39!=t.keyCode||(t.preventDefault(),a.selection.getSel().modify("move",37==t.keyCode?"backward":"forward","word"))})}function O(){s("AutoUrlDetect",!1)}var I=o.each,z=e.BACKSPACE,F=e.DELETE,W=a.dom,V=a.selection,U=a.settings,q=a.parser,j=a.serializer,$=i.gecko,K=i.ie,Y=i.webkit;C(),_(),u(),L(),Y&&(d(),p(),g(),k(),i.iOS?(y(),M(),D()):f()),K&&i.ie<11&&(m(),b(),x(),w(),T(),R(),A(),B()),i.ie>=11&&D(),i.ie&&(f(),O()),$&&(m(),h(),v(),N(),E(),S(),H(),P())}}),r(nt,[f],function(e){function t(){return!1}function n(){return!0}var r="__bindings",i=e.makeMap("focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave keydown keypress keyup contextmenu dragstart dragend dragover draggesture dragdrop drop drag"," ");return{fire:function(e,i,o){var a=this,s,l,c,d,u;if(e=e.toLowerCase(),i=i||{},i.type=e,i.target||(i.target=a),i.preventDefault||(i.preventDefault=function(){i.isDefaultPrevented=n},i.stopPropagation=function(){i.isPropagationStopped=n},i.stopImmediatePropagation=function(){i.isImmediatePropagationStopped=n},i.isDefaultPrevented=t,i.isPropagationStopped=t,i.isImmediatePropagationStopped=t),a[r]&&(s=a[r][e]))for(l=0,c=s.length;c>l&&(s[l]=d=s[l],!i.isImmediatePropagationStopped());l++)if(d.call(a,i)===!1)return i.preventDefault(),i;if(o!==!1&&a.parent)for(u=a.parent();u&&!i.isPropagationStopped();)u.fire(e,i,!1),u=u.parent();return i},on:function(e,t){var n=this,o,a,s,l;if(t===!1&&(t=function(){return!1}),t)for(s=e.toLowerCase().split(" "),l=s.length;l--;)e=s[l],o=n[r],o||(o=n[r]={}),a=o[e],a||(a=o[e]=[],n.bindNative&&i[e]&&n.bindNative(e)),a.push(t);return n},off:function(e,t){var n=this,o,a=n[r],s,l,c,d;if(a)if(e)for(c=e.toLowerCase().split(" "),o=c.length;o--;){if(e=c[o],s=a[e],!e){for(l in a)a[e].length=0;return n}if(s){if(t)for(d=s.length;d--;)s[d]===t&&s.splice(d,1);else s.length=0;!s.length&&n.unbindNative&&i[e]&&(n.unbindNative(e),delete a[e])}}else{if(n.unbindNative)for(e in a)n.unbindNative(e);n[r]=[]}return n},hasEventListeners:function(e){var t=this[r];return e=e.toLowerCase(),!(!t||!t[e]||0===t[e].length)}}}),r(rt,[f,h],function(e,t){var n=e.each,r=e.explode,i={f9:120,f10:121,f11:122};return function(o){var a=this,s={};o.on("keyup keypress keydown",function(e){(e.altKey||e.ctrlKey||e.metaKey)&&n(s,function(n){var r=t.mac?e.metaKey:e.ctrlKey;if(n.ctrl==r&&n.alt==e.altKey&&n.shift==e.shiftKey)return e.keyCode==n.keyCode||e.charCode&&e.charCode==n.charCode?(e.preventDefault(),"keydown"==e.type&&n.func.call(n.scope),!0):void 0})}),a.add=function(t,a,l,c){var d;return d=l,"string"==typeof l?l=function(){o.execCommand(d,!1,null)}:e.isArray(d)&&(l=function(){o.execCommand(d[0],d[1],d[2])}),n(r(t.toLowerCase()),function(e){var t={func:l,scope:c||o,desc:o.translate(a),alt:!1,ctrl:!1,shift:!1};n(r(e,"+"),function(e){switch(e){case"alt":case"ctrl":case"shift":t[e]=!0;break;default:t.charCode=e.charCodeAt(0),t.keyCode=i[e]||e.toUpperCase().charCodeAt(0)}}),s[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t}),!0}}}),r(it,[v,b,C,k,E,A,L,H,M,D,P,O,y,d,et,x,_,tt,h,f,nt,rt],function(e,n,r,i,o,a,s,l,c,d,u,f,p,m,h,g,v,y,b,C,x,w){function _(e,t){return"selectionchange"==t?e.getDoc():!e.inline&&/^mouse|click|contextmenu|drop/.test(t)?e.getDoc():e.getBody()}function N(e,t,r){var i=this,o,a;o=i.documentBaseUrl=r.documentBaseURL,a=r.baseURI,i.settings=t=T({id:e,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:o,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:!0,entity_encoding:"named",url_converter:i.convertURL,url_converter_scope:i,ie7_compat:!0},t),n.language=t.language||"en",n.languageLoad=t.language_load,n.baseURL=r.baseURL,i.id=t.id=e,i.isNotDirty=!0,i.plugins={},i.documentBaseURI=new f(t.document_base_url||o,{base_uri:a}),i.baseURI=a,i.contentCSS=[],i.contentStyles=[],i.shortcuts=new w(i),i.execCommands={},i.queryStateCommands={},i.queryValueCommands={},i.loadedCSS={},i.suffix=r.suffix,i.editorManager=r,i.inline=t.inline,r.fire("SetupEditor",i),i.execCallback("setup",i)}var E=e.DOM,k=n.ThemeManager,S=n.PluginManager,T=C.extend,R=C.each,A=C.explode,B=C.inArray,L=C.trim,H=C.resolve,M=m.Event,D=b.gecko,P=b.ie;return N.prototype={render:function(){function e(){E.unbind(window,"ready",e),n.render()}function t(){var e=p.ScriptLoader;if(r.language&&"en"!=r.language&&!r.language_url&&(r.language_url=n.editorManager.baseURL+"/langs/"+r.language+".js"),r.language_url&&e.add(r.language_url),r.theme&&"function"!=typeof r.theme&&"-"!=r.theme.charAt(0)&&!k.urls[r.theme]){var t=r.theme_url;t=t?n.documentBaseURI.toAbsolute(t):"themes/"+r.theme+"/theme"+o+".js",k.load(r.theme,t)}C.isArray(r.plugins)&&(r.plugins=r.plugins.join(" ")),R(r.external_plugins,function(e,t){S.load(t,e),r.plugins+=" "+t}),R(r.plugins.split(/[ ,]/),function(e){if(e=L(e),e&&!S.urls[e])if("-"==e.charAt(0)){e=e.substr(1,e.length);var t=S.dependencies(e);R(t,function(e){var t={prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"};e=S.createUrl(t,e),S.load(e.resource,e)})}else S.load(e,{prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"})}),e.loadQueue(function(){n.removed||n.init()})}var n=this,r=n.settings,i=n.id,o=n.suffix;if(!M.domLoaded)return void E.bind(window,"ready",e);if(n.getElement()&&b.contentEditable){r.inline?n.inline=!0:(n.orgVisibility=n.getElement().style.visibility,n.getElement().style.visibility="hidden");var a=n.getElement().form||E.getParent(i,"form");a&&(n.formElement=a,r.hidden_input&&!/TEXTAREA|INPUT/i.test(n.getElement().nodeName)&&(E.insertAfter(E.create("input",{type:"hidden",name:i}),i),n.hasHiddenInput=!0),n.formEventDelegate=function(e){n.fire(e.type,e)},E.bind(a,"submit reset",n.formEventDelegate),n.on("reset",function(){n.setContent(n.startContent,{format:"raw"})}),!r.submit_patch||a.submit.nodeType||a.submit.length||a._mceOldSubmit||(a._mceOldSubmit=a.submit,a.submit=function(){return n.editorManager.triggerSave(),n.isNotDirty=!0,a._mceOldSubmit(a)})),n.windowManager=new h(n),"xml"==r.encoding&&n.on("GetContent",function(e){e.save&&(e.content=E.encode(e.content))}),r.add_form_submit_trigger&&n.on("submit",function(){n.initialized&&n.save()}),r.add_unload_trigger&&(n._beforeUnload=function(){!n.initialized||n.destroyed||n.isHidden()||n.save({format:"raw",no_events:!0,set_dirty:!1})},n.editorManager.on("BeforeUnload",n._beforeUnload)),t()}},init:function(){function e(n){var r=S.get(n),i,o;i=S.urls[n]||t.documentBaseUrl.replace(/\/$/,""),n=L(n),r&&-1===B(m,n)&&(R(S.dependencies(n),function(t){e(t)}),o=new r(t,i),t.plugins[n]=o,o.init&&(o.init(t,i),m.push(n)))}var t=this,n=t.settings,r=t.getElement(),i,o,a,s,l,c,d,u,f,p,m=[];if(t.rtl=this.editorManager.i18n.rtl,t.editorManager.add(t),n.aria_label=n.aria_label||E.getAttrib(r,"aria-label",t.getLang("aria.rich_text_area")),n.theme&&("function"!=typeof n.theme?(n.theme=n.theme.replace(/-/,""),l=k.get(n.theme),t.theme=new l(t,k.urls[n.theme]),t.theme.init&&t.theme.init(t,k.urls[n.theme]||t.documentBaseUrl.replace(/\/$/,""))):t.theme=n.theme),R(n.plugins.replace(/\-/g,"").split(/[ ,]/),e),n.render_ui&&t.theme&&(t.orgDisplay=r.style.display,"function"!=typeof n.theme?(i=n.width||r.style.width||r.offsetWidth,o=n.height||r.style.height||r.offsetHeight,a=n.min_height||100,f=/^[0-9\.]+(|px)$/i,f.test(""+i)&&(i=Math.max(parseInt(i,10)+(l.deltaWidth||0),100)),f.test(""+o)&&(o=Math.max(parseInt(o,10)+(l.deltaHeight||0),a)),l=t.theme.renderUI({targetNode:r,width:i,height:o,deltaWidth:n.delta_width,deltaHeight:n.delta_height}),n.content_editable||(E.setStyles(l.sizeContainer||l.editorContainer,{wi2dth:i,h2eight:o}),o=(l.iframeHeight||o)+("number"==typeof o?l.deltaHeight||0:""),a>o&&(o=a))):(l=n.theme(t,r),l.editorContainer.nodeType&&(l.editorContainer=l.editorContainer.id=l.editorContainer.id||t.id+"_parent"),l.iframeContainer.nodeType&&(l.iframeContainer=l.iframeContainer.id=l.iframeContainer.id||t.id+"_iframecontainer"),o=l.iframeHeight||r.offsetHeight),t.editorContainer=l.editorContainer),n.content_css&&R(A(n.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),n.content_style&&t.contentStyles.push(n.content_style),n.content_editable)return r=s=l=null,t.initContentBody();for(t.iframeHTML=n.doctype+"",n.document_base_url!=t.documentBaseUrl&&(t.iframeHTML+=''),!b.caretAfter&&n.ie7_compat&&(t.iframeHTML+=''),t.iframeHTML+='',p=0;p',t.loadedCSS[h]=!0}d=n.body_id||"tinymce",-1!=d.indexOf("=")&&(d=t.getParam("body_id","","hash"),d=d[t.id]||d),u=n.body_class||"",-1!=u.indexOf("=")&&(u=t.getParam("body_class","","hash"),u=u[t.id]||""),t.iframeHTML+='
    ";var g='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinymce.get("'+t.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody(true);})()';if(document.domain!=location.hostname&&(c=g),s=E.add(l.iframeContainer,"iframe",{id:t.id+"_ifr",src:c||'javascript:""',frameBorder:"0",allowTransparency:"true",title:t.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),style:{width:"100%",height:o,display:"block"}}),P)try{t.getDoc() +}catch(v){s.src=c=g}t.contentAreaContainer=l.iframeContainer,l.editorContainer&&(E.get(l.editorContainer).style.display=t.orgDisplay),E.get(t.id).style.display="none",E.setAttrib(t.id,"aria-hidden",!0),c||t.initContentBody(),r=s=l=null},initContentBody:function(t){var n=this,o=n.settings,f=E.get(n.id),p=n.getDoc(),m,h;o.inline||(n.getElement().style.visibility=n.orgVisibility),t||o.content_editable||(p.open(),p.write(n.iframeHTML),p.close()),o.content_editable&&(n.on("remove",function(){var e=this.getBody();E.removeClass(e,"mce-content-body"),E.removeClass(e,"mce-edit-focus"),E.setAttrib(e,"tabIndex",null),E.setAttrib(e,"contentEditable",null)}),E.addClass(f,"mce-content-body"),f.tabIndex=-1,n.contentDocument=p=o.content_document||document,n.contentWindow=o.content_window||window,n.bodyElement=f,o.content_document=o.content_window=null,o.root_name=f.nodeName.toLowerCase()),m=n.getBody(),m.disabled=!0,o.readonly||(n.inline&&"static"==E.getStyle(m,"position",!0)&&(m.style.position="relative"),m.contentEditable=n.getParam("content_editable_state",!0)),m.disabled=!1,n.schema=new g(o),n.dom=new e(p,{keep_values:!0,url_converter:n.convertURL,url_converter_scope:n,hex_colors:o.force_hex_style_colors,class_filter:o.class_filter,update_styles:!0,root_element:o.content_editable?n.id:null,collect:o.content_editable,schema:n.schema,onSetAttrib:function(e){n.fire("SetAttrib",e)}}),n.parser=new v(o,n.schema),n.parser.addAttributeFilter("src,href,style",function(e,t){for(var r=e.length,i,o=n.dom,a,s;r--;)i=e[r],a=i.attr(t),s="data-mce-"+t,i.attributes.map[s]||("style"===t?i.attr(s,o.serializeStyle(o.parseStyle(a),i.name)):i.attr(s,n.convertURL(a,t,i.name)))}),n.parser.addNodeFilter("script",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("type","mce-"+(n.attr("type")||"text/javascript"))}),n.parser.addNodeFilter("#cdata",function(e){for(var t=e.length,n;t--;)n=e[t],n.type=8,n.name="#comment",n.value="[CDATA["+n.value+"]]"}),n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var t=e.length,i,o=n.schema.getNonEmptyElements();t--;)i=e[t],i.isEmpty(o)&&(i.empty().append(new r("br",1)).shortEnded=!0)}),n.serializer=new i(o,n),n.selection=new a(n.dom,n.getWin(),n.serializer,n),n.formatter=new s(n),n.undoManager=new l(n),n.forceBlocks=new d(n),n.enterKey=new c(n),n.editorCommands=new u(n),n.fire("PreInit"),o.browser_spellcheck||o.gecko_spellcheck||(p.body.spellcheck=!1,E.setAttrib(m,"spellcheck","false")),n.fire("PostRender"),n.quirks=y(n),o.directionality&&(m.dir=o.directionality),o.nowrap&&(m.style.whiteSpace="nowrap"),o.protect&&n.on("BeforeSetContent",function(e){R(o.protect,function(t){e.content=e.content.replace(t,function(e){return""})})}),n.on("SetContent",function(){n.addVisual(n.getBody())}),o.padd_empty_editor&&n.on("PostProcess",function(e){e.content=e.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
    [\r\n]*)$/,"")}),n.load({initial:!0,format:"html"}),n.startContent=n.getContent({format:"raw"}),n.initialized=!0,R(n._pendingNativeEvents,function(e){n.dom.bind(_(n,e),e,function(e){n.fire(e.type,e)})}),n.fire("init"),n.focus(!0),n.nodeChanged({initial:!0}),n.execCallback("init_instance_callback",n),n.contentStyles.length>0&&(h="",R(n.contentStyles,function(e){h+=e+"\r\n"}),n.dom.addStyle(h)),R(n.contentCSS,function(e){n.loadedCSS[e]||(n.dom.loadCSS(e),n.loadedCSS[e]=!0)}),o.auto_focus&&setTimeout(function(){var e=n.editorManager.get(o.auto_focus);e.selection.select(e.getBody(),1),e.selection.collapse(1),e.getBody().focus(),e.getWin().focus()},100),f=p=m=null},focus:function(e){var t,n=this,r=n.selection,i=n.settings.content_editable,o,a,s=n.getDoc(),l;e||(o=r.getRng(),o.item&&(a=o.item(0)),n._refreshContentEditable(),i||(b.opera||n.getBody().focus(),n.getWin().focus()),(D||i)&&(l=n.getBody(),l.setActive&&b.ie<11?l.setActive():l.focus(),i&&r.normalize()),a&&a.ownerDocument==s&&(o=s.body.createControlRange(),o.addElement(a),o.select())),n.editorManager.activeEditor!=n&&((t=n.editorManager.activeEditor)&&t.fire("deactivate",{relatedTarget:n}),n.fire("activate",{relatedTarget:t})),n.editorManager.activeEditor=n},execCallback:function(e){var t=this,n=t.settings[e],r;if(n)return t.callbackLookup&&(r=t.callbackLookup[e])&&(n=r.func,r=r.scope),"string"==typeof n&&(r=n.replace(/\.\w+$/,""),r=r?H(r):0,n=H(n),t.callbackLookup=t.callbackLookup||{},t.callbackLookup[e]={func:n,scope:r}),n.apply(r||t,Array.prototype.slice.call(arguments,1))},translate:function(e){var t=this.settings.language||"en",n=this.editorManager.i18n;return e?n.data[t+"."+e]||e.replace(/\{\#([^\}]+)\}/g,function(e,r){return n.data[t+"."+r]||"{#"+r+"}"}):""},getLang:function(e,n){return this.editorManager.i18n.data[(this.settings.language||"en")+"."+e]||(n!==t?n:"{#"+e+"}")},getParam:function(e,t,n){var r=e in this.settings?this.settings[e]:t,i;return"hash"===n?(i={},"string"==typeof r?R(r.split(r.indexOf("=")>0?/[;,](?![^=;,]*(?:[;,]|$))/:","),function(e){e=e.split("="),i[L(e[0])]=L(e.length>1?e[1]:e)}):i=r,i):r},nodeChanged:function(){var e=this,t=e.selection,n,r,i;e.initialized&&!e.settings.disable_nodechange&&(i=e.getBody(),n=t.getStart()||i,n=P&&n.ownerDocument!=e.getDoc()?e.getBody():n,"IMG"==n.nodeName&&t.isCollapsed()&&(n=n.parentNode),r=[],e.dom.getParent(n,function(e){return e===i?!0:void r.push(e)}),e.fire("NodeChange",{element:n,parents:r}))},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.text||t.icon||(t.icon=e),n.buttons=n.buttons||{},t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems||{},n.menuItems[e]=t},addCommand:function(e,t,n){this.execCommands[e]={func:t,scope:n||this}},addQueryStateHandler:function(e,t,n){this.queryStateCommands[e]={func:t,scope:n||this}},addQueryValueHandler:function(e,t,n){this.queryValueCommands[e]={func:t,scope:n||this}},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){var i=this,o=0,a;return/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(e)||r&&r.skip_focus||i.focus(),r=T({},r),r=i.fire("BeforeExecCommand",{command:e,ui:t,value:n}),r.isDefaultPrevented()?!1:(a=i.execCommands[e])&&a.func.call(a.scope,t,n)!==!0?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):(R(i.plugins,function(r){return r.execCommand&&r.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),o=!0,!1):void 0}),o?o:i.theme&&i.theme.execCommand&&i.theme.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):i.editorCommands.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):(i.getDoc().execCommand(e,t,n),void i.fire("ExecCommand",{command:e,ui:t,value:n})))},queryCommandState:function(e){var t=this,n,r;if(!t._isHidden()){if((n=t.queryStateCommands[e])&&(r=n.func.call(n.scope),r!==!0))return r;if(r=t.editorCommands.queryCommandState(e),-1!==r)return r;try{return t.getDoc().queryCommandState(e)}catch(i){}}},queryCommandValue:function(e){var n=this,r,i;if(!n._isHidden()){if((r=n.queryValueCommands[e])&&(i=r.func.call(r.scope),i!==!0))return i;if(i=n.editorCommands.queryCommandValue(e),i!==t)return i;try{return n.getDoc().queryCommandValue(e)}catch(o){}}},show:function(){var e=this;E.show(e.getContainer()),E.hide(e.id),e.load(),e.fire("show")},hide:function(){var e=this,t=e.getDoc();P&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),E.hide(e.getContainer()),E.setStyle(e.id,"display",e.orgDisplay),e.fire("hide")},isHidden:function(){return!E.isHidden(this.id)},setProgressState:function(e,t){this.fire("ProgressState",{state:e,time:t})},load:function(e){var n=this,r=n.getElement(),i;return r?(e=e||{},e.load=!0,i=n.setContent(r.value!==t?r.value:r.innerHTML,e),e.element=r,e.no_events||n.fire("LoadContent",e),e.element=r=null,i):void 0},save:function(e){var t=this,n=t.getElement(),r,i;if(n&&t.initialized)return e=e||{},e.save=!0,e.element=n,r=e.content=t.getContent(e),e.no_events||t.fire("SaveContent",e),r=e.content,/TEXTAREA|INPUT/i.test(n.nodeName)?n.value=r:(n.innerHTML=r,(i=E.getParent(t.id,"form"))&&R(i.elements,function(e){return e.name==t.id?(e.value=r,!1):void 0})),e.element=n=null,e.set_dirty!==!1&&(t.isNotDirty=!0),r},setContent:function(e,t){var n=this,r=n.getBody(),i;return t=t||{},t.format=t.format||"html",t.set=!0,t.content=e,t.no_events||n.fire("BeforeSetContent",t),e=t.content,0===e.length||/^\s+$/.test(e)?(i=n.settings.forced_root_block,i&&n.schema.isValidChild(r.nodeName.toLowerCase(),i.toLowerCase())?(e=P&&11>P?"":'
    ',e=n.dom.createHTML(i,n.settings.forced_root_block_attrs,e)):(!P||11>P)&&(e='
    '),r.innerHTML=e,n.fire("SetContent",t)):("raw"!==t.format&&(e=new o({},n.schema).serialize(n.parser.parse(e,{isRootContent:!0}))),t.content=L(e),n.dom.setHTML(r,t.content),t.no_events||n.fire("SetContent",t)),t.content},getContent:function(e){var t=this,n,r=t.getBody();return e=e||{},e.format=e.format||"html",e.get=!0,e.getInner=!0,e.no_events||t.fire("BeforeGetContent",e),n="raw"==e.format?r.innerHTML:"text"==e.format?r.innerText||r.textContent:t.serializer.serialize(r,e),e.content="text"!=e.format?L(n):n,e.no_events||t.fire("GetContent",e),e.content},insertContent:function(e){this.execCommand("mceInsertContent",!1,e)},isDirty:function(){return!this.isNotDirty},getContainer:function(){var e=this;return e.container||(e.container=E.get(e.editorContainer||e.id+"_parent")),e.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return E.get(this.settings.content_element||this.id)},getWin:function(){var e=this,t;return e.contentWindow||(t=E.get(e.id+"_ifr"),t&&(e.contentWindow=t.contentWindow)),e.contentWindow},getDoc:function(){var e=this,t;return e.contentDocument||(t=e.getWin(),t&&(e.contentDocument=t.document)),e.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(e,t,n){var r=this,i=r.settings;return i.urlconverter_callback?r.execCallback("urlconverter_callback",e,n,!0,t):!i.convert_urls||n&&"LINK"==n.nodeName||0===e.indexOf("file:")||0===e.length?e:i.relative_urls?r.documentBaseURI.toRelative(e):e=r.documentBaseURI.toAbsolute(e,i.remove_script_host)},addVisual:function(e){var n=this,r=n.settings,i=n.dom,o;e=e||n.getBody(),n.hasVisual===t&&(n.hasVisual=r.visual),R(i.select("table,a",e),function(e){var t;switch(e.nodeName){case"TABLE":return o=r.visual_table_class||"mce-item-table",t=i.getAttrib(e,"border"),void(t&&"0"!=t||(n.hasVisual?i.addClass(e,o):i.removeClass(e,o)));case"A":return void(i.getAttrib(e,"href",!1)||(t=i.getAttrib(e,"name")||e.id,o="mce-item-anchor",t&&(n.hasVisual?i.addClass(e,o):i.removeClass(e,o))))}}),n.fire("VisualAid",{element:e,hasVisual:n.hasVisual})},remove:function(){var e=this;if(!e.removed){e.removed=1,e.hasHiddenInput&&E.remove(e.getElement().nextSibling);var t=e.getDoc();P&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),E.setStyle(e.id,"display",e.orgDisplay),e.settings.content_editable||(M.unbind(e.getWin()),M.unbind(e.getDoc()));var n=e.getContainer();M.unbind(e.getBody()),M.unbind(n),e.fire("remove"),e.editorManager.remove(e),E.remove(n),e.destroy()}},bindNative:function(e){var t=this;t.settings.readonly||(t.initialized?t.dom.bind(_(t,e),e,function(n){t.fire(e,n)}):t._pendingNativeEvents?t._pendingNativeEvents.push(e):t._pendingNativeEvents=[e])},unbindNative:function(e){var t=this;t.initialized&&t.dom.unbind(e)},destroy:function(e){var t=this,n;if(!t.destroyed){if(!e&&!t.removed)return void t.remove();e&&D&&(M.unbind(t.getDoc()),M.unbind(t.getWin()),M.unbind(t.getBody())),e||(t.editorManager.off("beforeunload",t._beforeUnload),t.theme&&t.theme.destroy&&t.theme.destroy(),t.selection.destroy(),t.dom.destroy()),n=t.formElement,n&&(n._mceOldSubmit&&(n.submit=n._mceOldSubmit,n._mceOldSubmit=null),E.unbind(n,"submit reset",t.formEventDelegate)),t.contentAreaContainer=t.formElement=t.container=null,t.settings.content_element=t.bodyElement=t.contentDocument=t.contentWindow=null,t.selection&&(t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null),t.destroyed=1}},_refreshContentEditable:function(){var e=this,t,n;e._isHidden()&&(t=e.getBody(),n=t.parentNode,n.removeChild(t),n.appendChild(t),t.focus())},_isHidden:function(){var e;return D?(e=this.selection.getSel(),!e||!e.rangeCount||0===e.rangeCount):0}},T(N.prototype,x),N}),r(ot,[],function(){var e={};return{rtl:!1,add:function(t,n){for(var r in n)e[r]=n[r];this.rtl=this.rtl||"rtl"===e._dir},translate:function(t){if("undefined"==typeof t)return t;if("string"!=typeof t&&t.raw)return t.raw;if(t.push){var n=t.slice(1);t=(e[t[0]]||t[0]).replace(/\{([^\}]+)\}/g,function(e,t){return n[t]})}return e[t]||t},data:e}}),r(at,[v,h],function(e,t){function n(r){function i(){try{return document.activeElement}catch(e){return document.body}}function o(e){return e&&e.startContainer?{startContainer:e.startContainer,startOffset:e.startOffset,endContainer:e.endContainer,endOffset:e.endOffset}:e}function a(e,t){var n;return t.startContainer?(n=e.getDoc().createRange(),n.setStart(t.startContainer,t.startOffset),n.setEnd(t.endContainer,t.endOffset)):n=t,n}function s(t){return!!e.DOM.getParent(t,n.isEditorUIElement)}function l(e,t){for(var n=t.getBody();e;){if(e==n)return!0;e=e.parentNode}}function c(n){var c=n.editor,d;c.on("init",function(){"onbeforedeactivate"in document&&t.ie<11?c.dom.bind(c.getBody(),"beforedeactivate",function(){try{c.lastRng=c.selection.getRng()}catch(e){}c.selection.lastFocusBookmark=o(c.lastRng)}):(c.inline||t.ie>10)&&(c.on("nodechange keyup",function(){var e=document.activeElement;e&&e.id==c.id+"_ifr"&&(e=c.getBody()),l(e,c)&&(c.lastRng=c.selection.getRng())}),t.webkit&&(d=function(){var e=c.selection.getRng();e.collapsed||(c.lastRng=e)},e.DOM.bind(document,"selectionchange",d),c.on("remove",function(){e.DOM.unbind(document,"selectionchange",d)})))}),c.on("setcontent",function(){c.lastRng=null}),c.on("mousedown",function(){c.selection.lastFocusBookmark=null}),c.on("focusin",function(){var e=r.focusedEditor;c.selection.lastFocusBookmark&&(c.selection.setRng(a(c,c.selection.lastFocusBookmark)),c.selection.lastFocusBookmark=null),e!=c&&(e&&e.fire("blur",{focusedEditor:c}),r.activeEditor=c,r.focusedEditor=c,c.fire("focus",{blurredEditor:e}),c.focus(!1)),c.lastRng=null}),c.on("focusout",function(){window.setTimeout(function(){var e=r.focusedEditor;s(i())||e!=c||(c.fire("blur",{focusedEditor:null}),r.focusedEditor=null,c.selection&&(c.selection.lastFocusBookmark=null))},0)})}e.DOM.bind(document,"focusin",function(e){var t=r.activeEditor;t&&e.target.ownerDocument==document&&(t.selection&&(t.selection.lastFocusBookmark=o(t.lastRng)),s(e.target)||r.focusedEditor!=t||(t.fire("blur",{focusedEditor:null}),r.focusedEditor=null))}),r.on("AddEditor",c)}return n.isEditorUIElement=function(e){return-1!==e.className.indexOf("mce-")},n}),r(st,[it,v,O,h,f,nt,ot,at],function(e,n,r,i,o,a,s,l){var c=n.DOM,d=o.explode,u=o.each,f=o.extend,p=0,m,h={majorVersion:"4",minorVersion:"0.16",releaseDate:"2014-01-31",editors:[],i18n:s,activeEditor:null,setup:function(){var e=this,t,n,i="",o;if(n=document.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(n)||(n+="/"),o=window.tinymce||window.tinyMCEPreInit)t=o.base||o.baseURL,i=o.suffix;else for(var a=document.getElementsByTagName("script"),s=0;s0&&u(d(m),function(n){c.get(n)?(l=new e(n,t,a),s.push(l),l.render(!0)):u(document.forms,function(r){u(r.elements,function(r){r.name===n&&(n="mce_editor_"+p++,c.setAttrib(r,"id",n),l=new e(n,t,a),s.push(l),l.render(1))})})});break;case"textareas":case"specific_textareas":u(c.select("textarea"),function(r){t.editor_deselector&&i(r,t.editor_deselector)||(!t.editor_selector||i(r,t.editor_selector))&&(l=new e(n(r),t,a),s.push(l),l.render(!0))})}t.oninit&&(m=h=0,u(s,function(e){h++,e.initialized?m++:e.on("init",function(){m++,m==h&&r(t,"oninit")}),m==h&&r(t,"oninit")}))}var a=this,s=[],l;a.settings=t,c.bind(window,"ready",o)},get:function(e){return e===t?this.editors:this.editors[e]},add:function(e){var t=this,n=t.editors;return n[e.id]=e,n.push(e),t.activeEditor=e,t.fire("AddEditor",{editor:e}),m||(m=function(){t.fire("BeforeUnload")},c.bind(window,"beforeunload",m)),e},createEditor:function(t,n){return this.add(new e(t,n,this))},remove:function(e){var t=this,n,r=t.editors,i,o;{if(e){if("string"==typeof e)return e=e.selector||e,void u(c.select(e),function(e){t.remove(r[e.id])});if(i=e,!r[i.id])return null;for(delete r[i.id],n=0;n=0;n--)t.remove(r[n])}},execCommand:function(t,n,r){var i=this,o=i.get(r);switch(t){case"mceAddEditor":return i.get(r)||new e(r,i.settings,i).render(),!0;case"mceRemoveEditor":return o&&o.remove(),!0;case"mceToggleEditor":return o?(o.isHidden()?o.show():o.hide(),!0):(i.execCommand("mceAddEditor",0,r),!0)}return i.activeEditor?i.activeEditor.execCommand(t,n,r):!1},triggerSave:function(){u(this.editors,function(e){e.save()})},addI18n:function(e,t){s.add(e,t)},translate:function(e){return s.translate(e)}};return f(h,a),h.setup(),window.tinymce=window.tinyMCE=h,h}),r(lt,[st,f],function(e,t){var n=t.each,r=t.explode;e.on("AddEditor",function(e){var t=e.editor;t.on("preInit",function(){function e(e,t){n(t,function(t,n){t&&s.setStyle(e,n,t)}),s.rename(e,"span")}function i(e){s=t.dom,l.convert_fonts_to_spans&&n(s.select("font,u,strike",e.node),function(e){o[e.nodeName.toLowerCase()](s,e)})}var o,a,s,l=t.settings;l.inline_styles&&(a=r(l.font_size_legacy_values),o={font:function(t,n){e(n,{backgroundColor:n.style.backgroundColor,color:n.color,fontFamily:n.face,fontSize:a[parseInt(n.size,10)-1]})},u:function(t,n){e(n,{textDecoration:"underline"})},strike:function(t,n){e(n,{textDecoration:"line-through"})}},t.on("PreProcess SetContent",i))})})}),r(ct,[],function(){return{send:function(e){function t(){!e.async||4==n.readyState||r++>1e4?(e.success&&1e4>r&&200==n.status?e.success.call(e.success_scope,""+n.responseText,n,e):e.error&&e.error.call(e.error_scope,r>1e4?"TIMED_OUT":"GENERAL",n,e),n=null):setTimeout(t,10)}var n,r=0;if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=e.async===!1?!1:!0,e.data=e.data||"",n=new XMLHttpRequest){if(n.overrideMimeType&&n.overrideMimeType(e.content_type),n.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.content_type&&n.setRequestHeader("Content-Type",e.content_type),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send(e.data),!e.async)return t();setTimeout(t,10)}}}}),r(dt,[],function(){function e(t,n){var r,i,o,a;if(n=n||'"',null===t)return"null";if(o=typeof t,"string"==o)return i="\bb t\nn\ff\rr\"\"''\\\\",n+t.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=i.indexOf(t),r+1?"\\"+i.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e))})+n;if("object"==o){if(t.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(t)){for(r=0,i="[";r0?",":"")+e(t[r],n);return i+"]"}i="{";for(a in t)t.hasOwnProperty(a)&&(i+="function"!=typeof t[a]?(i.length>1?","+n:n)+a+n+":"+e(t[a],n):"");return i+"}"}return""+t}return{serialize:e,parse:function(e){try{return window[String.fromCharCode(101)+"val"]("("+e+")")}catch(t){}}}}),r(ut,[dt,ct,f],function(e,t,n){function r(e){this.settings=i({},e),this.count=0}var i=n.extend;return r.sendRPC=function(e){return(new r).send(e)},r.prototype={send:function(n){var r=n.error,o=n.success;n=i(this.settings,n),n.success=function(t,i){t=e.parse(t),"undefined"==typeof t&&(t={error:"JSON Parse error."}),t.error?r.call(n.error_scope||n.scope,t.error,i):o.call(n.success_scope||n.scope,t.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=e.serialize({id:n.id||"c"+this.count++,method:n.method,params:n.params}),n.content_type="application/json",t.send(n)}},r}),r(ft,[v],function(e){return{callbacks:{},count:0,send:function(n){var r=this,i=e.DOM,o=n.count!==t?n.count:r.count,a="tinymce_jsonp_"+o;r.callbacks[o]=function(e){i.remove(a),delete r.callbacks[o],n.callback(e)},i.add(i.doc.body,"script",{id:a,src:n.url,type:"text/javascript"}),r.count++}}}),r(pt,[],function(){function e(){s=[];for(var e in a)s.push(e);i.length=s.length}function n(){function n(e){var n,r;return r=e!==t?d+e:i.indexOf(",",d),-1===r||r>i.length?null:(n=i.substring(d,r),d=r+1,n)}var r,i,s,d=0;if(a={},c){o.load(l),i=o.getAttribute(l)||"";do{var u=n();if(null===u)break;if(r=n(parseInt(u,32)||0),null!==r){if(u=n(),null===u)break;s=n(parseInt(u,32)||0),r&&(a[r]=s)}}while(null!==r);e()}}function r(){var t,n="";if(c){for(var r in a)t=a[r],n+=(n?",":"")+r.length.toString(32)+","+r+","+t.length.toString(32)+","+t;o.setAttribute(l,n);try{o.save(l)}catch(i){}e()}}var i,o,a,s,l,c;try{if(window.localStorage)return localStorage}catch(d){}return l="tinymce",o=document.documentElement,c=!!o.addBehavior,c&&o.addBehavior("#default#userData"),i={key:function(e){return s[e]},getItem:function(e){return e in a?a[e]:null},setItem:function(e,t){a[e]=""+t,r()},removeItem:function(e){delete a[e],r()},clear:function(){a={},r()}},n(),i}),r(mt,[v,d,y,b,f,h],function(e,t,n,r,i,o){var a=window.tinymce;return a.DOM=e.DOM,a.ScriptLoader=n.ScriptLoader,a.PluginManager=r.PluginManager,a.ThemeManager=r.ThemeManager,a.dom=a.dom||{},a.dom.Event=t.Event,i.each(i,function(e,t){a[t]=e}),i.each("isOpera isWebKit isIE isGecko isMac".split(" "),function(e){a[e]=o[e.substr(2).toLowerCase()]}),{}}),r(ht,[I,f],function(e,t){return e.extend({Defaults:{firstControlClass:"first",lastControlClass:"last"},init:function(e){this.settings=t.extend({},this.Defaults,e)},preRender:function(e){e.addClass(this.settings.containerClass,"body")},applyClasses:function(e){var t=this,n=t.settings,r,i,o;r=e.items().filter(":visible"),i=n.firstControlClass,o=n.lastControlClass,r.each(function(e){e.removeClass(i).removeClass(o),n.controlClass&&e.addClass(n.controlClass)}),r.eq(0).addClass(i),r.eq(-1).addClass(o)},renderHtml:function(e){var t=this,n=t.settings,r,i="";return r=e.items(),r.eq(0).addClass(n.firstControlClass),r.eq(-1).addClass(n.lastControlClass),r.each(function(e){n.controlClass&&e.addClass(n.controlClass),i+=e.renderHtml()}),i},recalc:function(){},postRender:function(){}})}),r(gt,[ht],function(e){return e.extend({Defaults:{containerClass:"abs-layout",controlClass:"abs-layout-item"},recalc:function(e){e.items().filter(":visible").each(function(e){var t=e.settings;e.layoutRect({x:t.x,y:t.y,w:t.w,h:t.h}),e.recalc&&e.recalc()})},renderHtml:function(e){return'
    '+this._super(e)}})}),r(vt,[V,Y],function(e,t){return e.extend({Mixins:[t],Defaults:{classes:"widget tooltip tooltip-n"},text:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t._rendered&&(t.getEl().lastChild.innerHTML=t.encode(e)),t):t._value},renderHtml:function(){var e=this,t=e.classPrefix;return'"},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=131070}})}),r(yt,[V,vt],function(e,t){var n,r=e.extend({init:function(e){var t=this;t._super(e),t.canFocus=!0,e.tooltip&&r.tooltips!==!1&&(t.on("mouseenter",function(n){var r=t.tooltip().moveTo(-65535);if(n.control==t){var i=r.text(e.tooltip).show().testMoveRel(t.getEl(),["bc-tc","bc-tl","bc-tr"]);r.toggleClass("tooltip-n","bc-tc"==i),r.toggleClass("tooltip-nw","bc-tl"==i),r.toggleClass("tooltip-ne","bc-tr"==i),r.moveRel(t.getEl(),i)}else r.hide()}),t.on("mouseleave mousedown click",function(){t.tooltip().hide()})),t.aria("label",e.tooltip)},tooltip:function(){var e=this;return n||(n=new t({type:"tooltip"}),n.renderTo(e.getContainerElm())),n},active:function(e){var t=this,n;return e!==n&&(t.aria("pressed",e),t.toggleClass("active",e)),t._super(e)},disabled:function(e){var t=this,n;return e!==n&&(t.aria("disabled",e),t.toggleClass("disabled",e)),t._super(e)},postRender:function(){var e=this,t=e.settings;e._rendered=!0,e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&setTimeout(function(){e.focus()},0)},remove:function(){this._super(),n&&(n.remove(),n=null)}});return r}),r(bt,[yt],function(e){return e.extend({Defaults:{classes:"widget btn",role:"button"},init:function(e){var t=this,n;t.on("click mousedown",function(e){e.preventDefault()}),t._super(e),n=e.size,e.subtype&&t.addClass(e.subtype),n&&t.addClass("btn-"+n)},icon:function(e){var t=this,n=t.classPrefix;if("undefined"==typeof e)return t.settings.icon;if(t.settings.icon=e,e=e?n+"ico "+n+"i-"+t.settings.icon:"",t._rendered){var r=t.getEl().firstChild,i=r.getElementsByTagName("i")[0];e?(i&&i==r.firstChild||(i=document.createElement("i"),r.insertBefore(i,r.firstChild)),i.className=e):i&&r.removeChild(i),t.text(t._text)}return t},repaint:function(){var e=this.getEl().firstChild.style;e.width=e.height="100%",this._super()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon,i="";return e.settings.image&&(r="none",i=" style=\"background-image: url('"+e.settings.image+"')\""),r=e.settings.icon?n+"ico "+n+"i-"+r:"",'
    "}})}),r(Ct,[q],function(e){return e.extend({Defaults:{defaultType:"button",role:"toolbar"},renderHtml:function(){var e=this,t=e._layout;return e.addClass("btn-group"),e.preRender(),t.preRender(e),'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}})}),r(xt,[yt],function(e){return e.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(e){var t=this;t._super(e),t.on("click mousedown",function(e){e.preventDefault()}),t.on("click",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){var t=this;return"undefined"!=typeof e?(e?t.addClass("checked"):t.removeClass("checked"),t._checked=e,t.aria("checked",e),t):t._checked},value:function(e){return this.checked(e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
    '+e.encode(e._text)+"
    "}})}),r(wt,[bt,X],function(e,t){return e.extend({showPanel:function(){var e=this,n=e.settings;if(e.active(!0),e.panel)e.panel.show();else{var r=n.panel;r.type&&(r={layout:"grid",items:r}),r.popover=!0,r.autohide=!0,e.panel=new t(r).on("hide",function(){e.active(!1)}).parent(e).renderTo(e.getContainerElm()),e.panel.fire("show"),e.panel.reflow()}e.panel.moveRel(e.getEl(),n.popoverAlign||(e.isRtl()?["bc-tr","bc-tc"]:["bc-tl","bc-tc"]))},hidePanel:function(){var e=this;e.panel&&e.panel.hide()},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&(e.panel&&e.panel.visible()?e.hidePanel():e.showPanel())}),e._super()}})}),r(_t,[wt,v],function(e,t){var n=t.DOM;return e.extend({init:function(e){this._super(e),this.addClass("colorbutton")},color:function(e){return e?(this._color=e,this.getEl("preview").style.backgroundColor=e,this):this._color},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"",i=e.settings.image?" style=\"background-image: url('"+e.settings.image+"')\"":"";return'
    '},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(r){r.control!=e||n.getParent(r.target,"."+e.classPrefix+"open")||(r.stopImmediatePropagation(),t.call(e,r))}),delete e.settings.onclick,e._super()}})}),r(Nt,[yt,U,W],function(e,t,n){return e.extend({init:function(e){var t=this;t._super(e),t.addClass("combobox"),t.subinput=!0,e=t.settings,e.menu=e.menu||e.values,e.menu&&(e.icon="caret"),t.on("click",function(n){for(var r=n.target;r;)r.id&&-1!=r.id.indexOf("-open")&&(t.fire("action"),e.menu&&(t.showMenu(),n.keyboard&&t.menu.items()[0].focus())),r=r.parentNode}),t.on("keydown",function(e){"INPUT"==e.target.nodeName&&13==e.keyCode&&t.parents().reverse().each(function(n){return e.preventDefault(),t.fire("change"),n.hasEventListeners("submit")&&n.toJSON?(n.fire("submit",{data:n.toJSON()}),!1):void 0})}),e.placeholder&&(t.addClass("placeholder"),t.on("focusin",function(){t._hasOnChange||(n.on(t.getEl("inp"),"change",function(){t.fire("change")}),t._hasOnChange=!0),t.hasClass("placeholder")&&(t.getEl("inp").value="",t.removeClass("placeholder"))}),t.on("focusout",function(){0===t.value().length&&(t.getEl("inp").value=e.placeholder,t.addClass("placeholder"))}))},showMenu:function(){var e=this,n=e.settings,r;e.menu||(r=n.menu||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control===e.menu&&e.focus()}),e.menu.on("show hide",function(t){t.control.items().each(function(t){t.active(t.value()==e.value())})}).fire("show"),e.menu.on("select",function(t){e.value(t.control.value())}),e.on("focusin",function(t){"INPUT"==t.target.tagName&&e.menu.hide()}),e.aria("expanded",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),e.menu.moveRel(e.getEl(),e.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"])},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t.removeClass("placeholder"),t._rendered&&(t.getEl("inp").value=e),t):t._rendered?(e=t.getEl("inp").value,e!=t.settings.placeholder?e:""):t._value},disabled:function(e){var t=this;return t._rendered&&"undefined"!=typeof e&&(t.getEl("inp").disabled=e),t._super(e)},focus:function(){this.getEl("inp").focus()},repaint:function(){var e=this,t=e.getEl(),r=e.getEl("open"),i=e.layoutRect(),o,a;o=r?i.w-n.getSize(r).width-10:i.w-10;var s=document;return s.all&&(!s.documentMode||s.documentMode<=8)&&(a=e.layoutRect().h-2+"px"),n.css(t.firstChild,{width:o,lineHeight:a}),e._super(),e},postRender:function(){var e=this;return n.on(this.getEl("inp"),"change",function(){e.fire("change")}),e._super()},remove:function(){n.off(this.getEl("inp")),this._super()},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=n.value||n.placeholder||"",o,a,s="",l="";return"spellcheck"in n&&(l+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(l+=' maxlength="'+n.maxLength+'"'),n.size&&(l+=' size="'+n.size+'"'),n.subtype&&(l+=' type="'+n.subtype+'"'),e.disabled()&&(l+=' disabled="disabled"'),o=n.icon,o&&"caret"!=o&&(o=r+"ico "+r+"i-"+n.icon),a=e._text,(o||a)&&(s='
    ",e.addClass("has-open")),'
    "+s+"
    " +}})}),r(Et,[yt,J],function(e,t){return e.extend({init:function(e){var t=this;e.delimiter||(e.delimiter="\xbb"),t._super(e),t.addClass("path"),t.canFocus=!0,t.on("click",function(e){var n,r=e.target;(n=r.getAttribute("data-index"))&&t.fire("select",{value:t.data()[n],index:n})})},focus:function(){var e=this;return e.keyNav=new t({root:e,enableLeftRight:!0}),e.keyNav.focusFirst(),e},data:function(e){var t=this;return"undefined"!=typeof e?(t._data=e,t.update(),t):t._data},update:function(){this.innerHtml(this._getPathHtml())},postRender:function(){var e=this;e._super(),e.data(e.settings.data)},renderHtml:function(){var e=this;return'
    '+e._getPathHtml()+"
    "},_getPathHtml:function(){var e=this,t=e._data||[],n,r,i="",o=e.classPrefix;for(n=0,r=t.length;r>n;n++)i+=(n>0?'":"")+'
    '+t[n].name+"
    ";return i||(i='
     
    '),i}})}),r(kt,[Et,st],function(e,t){return e.extend({postRender:function(){function e(e){if(1===e.nodeType){if("BR"==e.nodeName||e.getAttribute("data-mce-bogus"))return!0;if("bookmark"===e.getAttribute("data-mce-type"))return!0}return!1}var n=this,r=t.activeEditor;return n.on("select",function(t){var n=[],i,o=r.getBody();for(r.focus(),i=r.selection.getStart();i&&i!=o;)e(i)||n.push(i),i=i.parentNode;r.selection.select(n[n.length-1-t.index]),r.nodeChanged()}),r.on("nodeChange",function(t){for(var i=[],o=t.parents,a=o.length;a--;)if(1==o[a].nodeType&&!e(o[a])){var s=r.fire("ResolveName",{name:o[a].nodeName.toLowerCase(),target:o[a]});i.push({name:s.name})}n.data(i)}),n._super()}})}),r(St,[q],function(e){return e.extend({Defaults:{layout:"flex",align:"center",defaults:{flex:1}},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.addClass("formitem"),t.preRender(e),'
    '+(e.settings.title?'
    '+e.settings.title+"
    ":"")+'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}})}),r(Tt,[q,St],function(e,t){return e.extend({Defaults:{containerCls:"form",layout:"flex",direction:"column",align:"stretch",flex:1,padding:20,labelGap:30,spacing:10,callbacks:{submit:function(){this.submit()}}},preRender:function(){var e=this,n=e.items();n.each(function(n){var r,i=n.settings.label;i&&(r=new t({layout:"flex",autoResize:"overflow",defaults:{flex:1},items:[{type:"label",text:i,flex:0,forId:n._id,disabled:n.disabled()}]}),r.type="formitem","undefined"==typeof n.settings.flex&&(n.settings.flex=1),e.replace(n,r),r.add(n))})},recalcLabels:function(){var e=this,t=0,n=[],r,i;if(e.settings.labelGapCalc!==!1)for(e.items().filter("formitem").each(function(e){var r=e.items()[0],i=r.getEl().clientWidth;t=i>t?i:t,n.push(r)}),i=e.settings.labelGap||0,r=n.length;r--;)n[r].settings.minWidth=t+i},visible:function(e){var t=this._super(e);return e===!0&&this._rendered&&this.recalcLabels(),t},submit:function(){return this.fire("submit",{data:this.toJSON()})},postRender:function(){var e=this;e._super(),e.recalcLabels(),e.fromJSON(e.settings.data)}})}),r(Rt,[Tt],function(e){return e.extend({Defaults:{containerCls:"fieldset",layout:"flex",direction:"column",align:"stretch",flex:1,padding:"25 15 5 15",labelGap:30,spacing:10,border:1},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.preRender(),t.preRender(e),'
    '+(e.settings.title?''+e.settings.title+"":"")+'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}})}),r(At,[Nt],function(e){return e.extend({init:function(e){var t=this,n=tinymce.activeEditor,r;e.spellcheck=!1,r=n.settings.file_browser_callback,r&&(e.icon="browse",e.onaction=function(){r(t.getEl("inp").id,t.getEl("inp").value,e.filetype,window)}),t._super(e)}})}),r(Bt,[gt],function(e){return e.extend({recalc:function(e){var t=e.layoutRect(),n=e.paddingBox();e.items().filter(":visible").each(function(e){e.layoutRect({x:n.left,y:n.top,w:t.innerW-n.right-n.left,h:t.innerH-n.top-n.bottom}),e.recalc&&e.recalc()})}})}),r(Lt,[gt],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,c,d,u,f,p,m,h,g,v=[],y,b,C,x,w,_,N,E,k,S,T,R,A,B,L,H,M,D,P,O,I,z,F,W,V=Math.max,U=Math.min;for(r=e.items().filter(":visible"),i=e.layoutRect(),o=e._paddingBox,a=e.settings,f=e.isRtl()?a.direction||"row-reversed":a.direction,s=a.align,l=e.isRtl()?a.pack||"end":a.pack,c=a.spacing||0,("row-reversed"==f||"column-reverse"==f)&&(r=r.set(r.toArray().reverse()),f=f.split("-")[0]),"column"==f?(k="y",N="h",E="minH",S="maxH",R="innerH",T="top",A="bottom",B="deltaH",L="contentH",I="left",D="w",H="x",M="innerW",P="minW",O="maxW",z="right",F="deltaW",W="contentW"):(k="x",N="w",E="minW",S="maxW",R="innerW",T="left",A="right",B="deltaW",L="contentW",I="top",D="h",H="y",M="innerH",P="minH",O="maxH",z="bottom",F="deltaH",W="contentH"),u=i[R]-o[T]-o[T],_=d=0,t=0,n=r.length;n>t;t++)p=r[t],m=p.layoutRect(),h=p.settings,g=h.flex,u-=n-1>t?c:0,g>0&&(d+=g,m[S]&&v.push(p),m.flex=g),u-=m[E],y=o[I]+m[P]+o[z],y>_&&(_=y);if(x={},x[E]=0>u?i[E]-u+i[B]:i[R]-u+i[B],x[P]=_+i[F],x[L]=i[R]-u,x[W]=_,x.minW=U(x.minW,i.maxW),x.minH=U(x.minH,i.maxH),x.minW=V(x.minW,i.startMinWidth),x.minH=V(x.minH,i.startMinHeight),!i.autoResize||x.minW==i.minW&&x.minH==i.minH){for(C=u/d,t=0,n=v.length;n>t;t++)p=v[t],m=p.layoutRect(),b=m[S],y=m[E]+m.flex*C,y>b?(u-=m[S]-m[E],d-=m.flex,m.flex=0,m.maxFlexSize=b):m.maxFlexSize=0;for(C=u/d,w=o[T],x={},0===d&&("end"==l?w=u+o[T]:"center"==l?(w=Math.round(i[R]/2-(i[R]-u)/2)+o[T],0>w&&(w=o[T])):"justify"==l&&(w=o[T],c=Math.floor(u/(r.length-1)))),x[H]=o[I],t=0,n=r.length;n>t;t++)p=r[t],m=p.layoutRect(),y=m.maxFlexSize||m[E],"center"===s?x[H]=Math.round(i[M]/2-m[D]/2):"stretch"===s?(x[D]=V(m[P]||0,i[M]-o[I]-o[z]),x[H]=o[I]):"end"===s&&(x[H]=i[M]-m[D]-o.top),m.flex>0&&(y+=m.flex*C),x[N]=y,x[k]=w,p.layoutRect(x),p.recalc&&p.recalc(),w+=y+c}else if(x.w=x.minW,x.h=x.minH,e.layoutRect(x),this.recalc(e),null===e._lastRect){var q=e.parent();q&&(q._lastRect=null,q.recalc())}}})}),r(Ht,[ht],function(e){return e.extend({Defaults:{containerClass:"flow-layout",controlClass:"flow-layout-item",endClass:"break"},recalc:function(e){e.items().filter(":visible").each(function(e){e.recalc&&e.recalc()})}})}),r(Mt,[V,yt,X,f,st,h],function(e,t,n,r,i,o){function a(e){function t(t){function n(e){return e.replace(/%(\w+)/g,"")}var r,i,o=e.dom,a="",l,c;return c=e.settings.preview_styles,c===!1?"":(c||(c="font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow"),(t=e.formatter.get(t))?(t=t[0],r=t.block||t.inline||"span",i=o.create(r),s(t.styles,function(e,t){e=n(e),e&&o.setStyle(i,t,e)}),s(t.attributes,function(e,t){e=n(e),e&&o.setAttrib(i,t,e)}),s(t.classes,function(e){e=n(e),o.hasClass(i,e)||o.addClass(i,e)}),e.fire("PreviewFormats"),o.setStyles(i,{position:"absolute",left:-65535}),e.getBody().appendChild(i),l=o.getStyle(e.getBody(),"fontSize",!0),l=/px$/.test(l)?parseInt(l,10):0,s(c.split(" "),function(t){var n=o.getStyle(i,t,!0);if(!("background-color"==t&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(n)&&(n=o.getStyle(e.getBody(),t,!0),"#ffffff"==o.toHex(n).toLowerCase())||"color"==t&&"#000000"==o.toHex(n).toLowerCase())){if("font-size"==t&&/em|%$/.test(n)){if(0===l)return;n=parseFloat(n,10)/(/%$/.test(n)?100:1),n=n*l+"px"}"border"==t&&n&&(a+="padding:0 2px;"),a+=t+":"+n+";"}}),e.fire("AfterPreviewFormats"),o.remove(i),a):void 0)}function r(t,n){return function(){var r=this;e.on("nodeChange",function(i){var o=e.formatter,a=null;s(i.parents,function(e){return s(t,function(t){return n?o.matchNode(e,n,{value:t.value})&&(a=t.value):o.matchNode(e,t.value)&&(a=t.value),a?!1:void 0}),a?!1:void 0}),r.value(a)})}}function i(e){e=e.split(";");for(var t=e.length;t--;)e[t]=e[t].split("=");return e}function o(){function n(e){var t=[];if(e)return s(e,function(e){var r={text:e.title,icon:e.icon};if(e.items)r.menu=n(e.items);else{var a=e.format||"custom"+i++;e.format||(e.name=a,o.push(e)),r.format=a}t.push(r)}),t}function r(){var t;return t=n(e.settings.style_formats_merge?e.settings.style_formats?a.concat(e.settings.style_formats):a:e.settings.style_formats||a)}var i=0,o=[],a=[{title:"Headers",items:[{title:"Header 1",format:"h1"},{title:"Header 2",format:"h2"},{title:"Header 3",format:"h3"},{title:"Header 4",format:"h4"},{title:"Header 5",format:"h5"},{title:"Header 6",format:"h6"}]},{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}];return e.on("init",function(){s(o,function(t){e.formatter.register(t.name,t)})}),{type:"menu",items:r(),onPostRender:function(t){e.fire("renderFormatsMenu",{control:t.control})},itemDefaults:{preview:!0,textStyle:function(){return this.settings.format?t(this.settings.format):void 0},onPostRender:function(){var t=this,n=this.settings.format;n&&t.parent().on("show",function(){t.disabled(!e.formatter.canApply(n)),t.active(e.formatter.match(n))})},onclick:function(){this.settings.format&&f(this.settings.format)}}}}function a(){return e.undoManager?e.undoManager.hasUndo():!1}function l(){return e.undoManager?e.undoManager.hasRedo():!1}function c(){var t=this;t.disabled(!a()),e.on("Undo Redo AddUndo TypingUndo",function(){t.disabled(!a())})}function d(){var t=this;t.disabled(!l()),e.on("Undo Redo AddUndo TypingUndo",function(){t.disabled(!l())})}function u(){var t=this;e.on("VisualAid",function(e){t.active(e.hasVisual)}),t.active(e.hasVisual)}function f(t){t.control&&(t=t.control.value()),t&&e.execCommand("mceToggleFormat",!1,t)}var p;p=o(),s({bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript"},function(t,n){e.addButton(n,{tooltip:t,onPostRender:function(){var t=this;e.formatter?e.formatter.formatChanged(n,function(e){t.active(e)}):e.on("init",function(){e.formatter.formatChanged(n,function(e){t.active(e)})})},onclick:function(){f(n)}})}),s({outdent:["Decrease indent","Outdent"],indent:["Increase indent","Indent"],cut:["Cut","Cut"],copy:["Copy","Copy"],paste:["Paste","Paste"],help:["Help","mceHelp"],selectall:["Select all","SelectAll"],hr:["Insert horizontal rule","InsertHorizontalRule"],removeformat:["Clear formatting","RemoveFormat"],visualaid:["Visual aids","mceToggleVisualAid"],newdocument:["New document","mceNewDocument"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1]})}),s({blockquote:["Blockquote","mceBlockQuote"],numlist:["Numbered list","InsertOrderedList"],bullist:["Bullet list","InsertUnorderedList"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],alignleft:["Align left","JustifyLeft"],aligncenter:["Align center","JustifyCenter"],alignright:["Align right","JustifyRight"],alignjustify:["Justify","JustifyFull"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1],onPostRender:function(){var t=this;e.formatter?e.formatter.formatChanged(n,function(e){t.active(e)}):e.on("init",function(){e.formatter.formatChanged(n,function(e){t.active(e)})})}})}),e.addButton("undo",{tooltip:"Undo",onPostRender:c,cmd:"undo"}),e.addButton("redo",{tooltip:"Redo",onPostRender:d,cmd:"redo"}),e.addMenuItem("newdocument",{text:"New document",shortcut:"Ctrl+N",icon:"newdocument",cmd:"mceNewDocument"}),e.addMenuItem("undo",{text:"Undo",icon:"undo",shortcut:"Ctrl+Z",onPostRender:c,cmd:"undo"}),e.addMenuItem("redo",{text:"Redo",icon:"redo",shortcut:"Ctrl+Y",onPostRender:d,cmd:"redo"}),e.addMenuItem("visualaid",{text:"Visual aids",selectable:!0,onPostRender:u,cmd:"mceToggleVisualAid"}),s({cut:["Cut","Cut","Ctrl+X"],copy:["Copy","Copy","Ctrl+C"],paste:["Paste","Paste","Ctrl+V"],selectall:["Select all","SelectAll","Ctrl+A"],bold:["Bold","Bold","Ctrl+B"],italic:["Italic","Italic","Ctrl+I"],underline:["Underline","Underline"],strikethrough:["Strikethrough","Strikethrough"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],removeformat:["Clear formatting","RemoveFormat"]},function(t,n){e.addMenuItem(n,{text:t[0],icon:n,shortcut:t[2],cmd:t[1]})}),e.on("mousedown",function(){n.hideAll()}),e.addButton("styleselect",{type:"menubutton",text:"Formats",menu:p}),e.addButton("formatselect",function(){var n=[],o=i(e.settings.block_formats||"Paragraph=p;Address=address;Pre=pre;Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6");return s(o,function(e){n.push({text:e[0],value:e[1],textStyle:function(){return t(e[1])}})}),{type:"listbox",text:o[0][0],values:n,fixedWidth:!0,onselect:f,onPostRender:r(n)}}),e.addButton("fontselect",function(){var t="Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",n=[],o=i(e.settings.font_formats||t);return s(o,function(e){n.push({text:{raw:e[0]},value:e[1],textStyle:-1==e[1].indexOf("dings")?"font-family:"+e[1]:""})}),{type:"listbox",text:"Font Family",tooltip:"Font Family",values:n,fixedWidth:!0,onPostRender:r(n,"fontname"),onselect:function(t){t.control.settings.value&&e.execCommand("FontName",!1,t.control.settings.value)}}}),e.addButton("fontsizeselect",function(){var t=[],n="8pt 10pt 12pt 14pt 18pt 24pt 36pt",i=e.settings.fontsize_formats||n;return s(i.split(" "),function(e){t.push({text:e,value:e})}),{type:"listbox",text:"Font Sizes",tooltip:"Font Sizes",values:t,fixedWidth:!0,onPostRender:r(t,"fontsize"),onclick:function(t){t.control.settings.value&&e.execCommand("FontSize",!1,t.control.settings.value)}}}),e.addMenuItem("formats",{text:"Formats",menu:p})}var s=r.each;i.on("AddEditor",function(t){t.editor.rtl&&(e.rtl=!0),a(t.editor)}),e.translate=function(e){return i.translate(e)},t.tooltips=!o.iOS}),r(Dt,[gt],function(e){return e.extend({recalc:function(e){var t=e.settings,n,r,i,o,a,s,l,c,d,u,f,p,m,h,g,v,y,b,C,x,w,_,N=[],E=[],k,S,T,R,A,B;for(t=e.settings,i=e.items().filter(":visible"),o=e.layoutRect(),r=t.columns||Math.ceil(Math.sqrt(i.length)),n=Math.ceil(i.length/r),y=t.spacingH||t.spacing||0,b=t.spacingV||t.spacing||0,C=t.alignH||t.align,x=t.alignV||t.align,g=e._paddingBox,C&&"string"==typeof C&&(C=[C]),x&&"string"==typeof x&&(x=[x]),u=0;r>u;u++)N.push(0);for(f=0;n>f;f++)E.push(0);for(f=0;n>f;f++)for(u=0;r>u&&(d=i[f*r+u],d);u++)c=d.layoutRect(),k=c.minW,S=c.minH,N[u]=k>N[u]?k:N[u],E[f]=S>E[f]?S:E[f];for(A=o.innerW-g.left-g.right,w=0,u=0;r>u;u++)w+=N[u]+(u>0?y:0),A-=(u>0?y:0)+N[u];for(B=o.innerH-g.top-g.bottom,_=0,f=0;n>f;f++)_+=E[f]+(f>0?b:0),B-=(f>0?b:0)+E[f];if(w+=g.left+g.right,_+=g.top+g.bottom,l={},l.minW=w+(o.w-o.innerW),l.minH=_+(o.h-o.innerH),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH,l.minW=Math.min(l.minW,o.maxW),l.minH=Math.min(l.minH,o.maxH),l.minW=Math.max(l.minW,o.startMinWidth),l.minH=Math.max(l.minH,o.startMinHeight),!o.autoResize||l.minW==o.minW&&l.minH==o.minH){o.autoResize&&(l=e.layoutRect(l),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH);var L;L="start"==t.packV?0:B>0?Math.floor(B/n):0;var H=0,M=t.flexWidths;if(M)for(u=0;uu;u++)N[u]+=M?M[u]*D:D;for(m=g.top,f=0;n>f;f++){for(p=g.left,s=E[f]+L,u=0;r>u&&(d=i[f*r+u],d);u++)h=d.settings,c=d.layoutRect(),a=Math.max(N[u],c.startMinWidth),T=R=0,c.x=p,c.y=m,v=h.alignH||(C?C[u]||C[0]:null),"center"==v?c.x=p+a/2-c.w/2:"right"==v?c.x=p+a-c.w:"stretch"==v&&(c.w=a),v=h.alignV||(x?x[u]||x[0]:null),"center"==v?c.y=m+s/2-c.h/2:"bottom"==v?c.y=m+s-c.h:"stretch"==v&&(c.h=s),d.layoutRect(c),p+=a+y,d.recalc&&d.recalc();m+=s+b}}else if(l.w=l.minW,l.h=l.minH,e.layoutRect(l),this.recalc(e),null===e._lastRect){var P=e.parent();P&&(P._lastRect=null,P.recalc())}}})}),r(Pt,[yt],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass("iframe"),e.canFocus=!1,''},src:function(e){this.getEl().src=e},html:function(e,t){var n=this,r=this.getEl().contentWindow.document.body;return r?(r.innerHTML=e,t&&t()):setTimeout(function(){n.html(e)},0),this}})}),r(Ot,[yt,W],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t.addClass("widget"),t.addClass("label"),t.canFocus=!1,e.multiline&&t.addClass("autoscroll"),e.strong&&t.addClass("strong")},initLayoutRect:function(){var e=this,n=e._super();if(e.settings.multiline){var r=t.getSize(e.getEl());r.width>n.maxW&&(n.minW=n.maxW,e.addClass("multiline")),e.getEl().style.width=n.minW+"px",n.startMinH=n.h=n.minH=Math.min(n.maxH,t.getSize(e.getEl()).height)}return n},repaint:function(){var e=this;return e.settings.multiline||(e.getEl().style.lineHeight=e.layoutRect().h+"px"),e._super()},text:function(e){var t=this;return t._rendered&&e&&this.innerHtml(t.encode(e)),t._super(e)},renderHtml:function(){var e=this,t=e.settings.forId;return'"}})}),r(It,[q,J],function(e,t){return e.extend({Defaults:{role:"toolbar",layout:"flow"},init:function(e){var t=this;t._super(e),t.addClass("toolbar")},postRender:function(){var e=this;return e.items().addClass("toolbar-item"),e.keyNav=new t({root:e,enableLeftRight:!0}),e._super()}})}),r(zt,[It],function(e){return e.extend({Defaults:{role:"menubar",containerCls:"menubar",defaults:{type:"menubutton"}}})}),r(Ft,[bt,U,zt],function(e,t,n){function r(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}var i=e.extend({init:function(e){var t=this;t._renderOpen=!0,t._super(e),t.addClass("menubtn"),e.fixedWidth&&t.addClass("fixed-width"),t.aria("haspopup",!0),t.hasPopup=!0},showMenu:function(){var e=this,n=e.settings,r;return e.menu&&e.menu.visible()?e.hideMenu():(e.menu||(r=n.menu||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control===e.menu&&e.focus()}),e.menu.on("show hide",function(t){t.control==e.menu&&e.activeMenu("show"==t.type)}).fire("show"),e.aria("expanded",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),void e.menu.moveRel(e.getEl(),e.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"]))},hideMenu:function(){var e=this;e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide(),e.aria("expanded",!1))},activeMenu:function(e){this.toggleClass("active",e)},renderHtml:function(){var e=this,t=e._id,r=e.classPrefix,i=e.settings.icon?r+"ico "+r+"i-"+e.settings.icon:"";return e.aria("role",e.parent()instanceof n?"menuitem":"button"),'
    '},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&r(t.target,e.getEl())&&(e.showMenu(),t.keyboard&&e.menu.items()[0].focus())}),e.on("mouseenter",function(t){var n=t.control,r=e.parent(),o;n&&r&&n instanceof i&&n.parent()==r&&(r.items().filter("MenuButton").each(function(e){e.hideMenu&&e!=n&&(e.menu&&e.menu.visible()&&(o=!0),e.hideMenu())}),o&&(n.focus(),n.showMenu()))}),e._super()},text:function(e){var t=this,n,r;if(t._rendered)for(r=t.getEl("open").getElementsByTagName("span"),n=0;n'+("-"!==o?' ":"")+("-"!==o?''+o+"":"")+(l?'
    '+l+"
    ":"")+(r.menu?'
    ':"")+""},postRender:function(){var e=this,t=e.settings,n=t.textStyle;if("function"==typeof n&&(n=n.call(this)),n){var r=e.getEl("text");r&&r.setAttribute("style",n)}return e._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),r(Ut,[X,J,Vt,f],function(e,t,n,r){var i=e.extend({Defaults:{defaultType:"menuitem",border:1,layout:"stack",role:"menu"},init:function(e){var i=this;if(e.autohide=!0,e.constrainToViewport=!0,e.itemDefaults)for(var o=e.items,a=o.length;a--;)o[a]=r.extend({},e.itemDefaults,o[a]);i._super(e),i.addClass("menu"),i.keyNav=new t({root:i,enableUpDown:!0,enableLeftRight:!0,leftAction:function(){i.parent()instanceof n&&i.keyNav.cancel()},onCancel:function(){i.fire("cancel",{},!1),i.hide()}})},repaint:function(){return this.toggleClass("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){var e=this;e.hideAll(),e.fire("cancel"),e.fire("select")},hideAll:function(){var e=this;return this.find("menuitem").exec("hideMenu"),e._super()},preRender:function(){var e=this;return e.items().each(function(t){var n=t.settings;return n.icon||n.selectable?(e._hasIcons=!0,!1):void 0}),e._super()}});return i}),r(qt,[xt],function(e){return e.extend({Defaults:{classes:"radio",role:"radio"}})}),r(jt,[yt,j],function(e,t){return e.extend({renderHtml:function(){var e=this,t=e.classPrefix;return e.addClass("resizehandle"),"both"==e.settings.direction&&e.addClass("resizehandle-both"),e.canFocus=!1,'
    '},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire("ResizeStart")},drag:function(t){"both"!=e.settings.direction&&(t.deltaX=0),e.fire("Resize",t)},stop:function(){e.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}})}),r($t,[yt],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass("spacer"),e.canFocus=!1,'
    '}})}),r(Kt,[Ft,W],function(e,t){return e.extend({Defaults:{classes:"widget btn splitbtn",role:"splitbutton"},repaint:function(){var e=this,n=e.getEl(),r=e.layoutRect(),i,o;return e._super(),i=n.firstChild,o=n.lastChild,t.css(i,{width:r.w-t.getSize(o).width,height:r.h-2}),t.css(o,{height:r.h-2}),e},activeMenu:function(e){var n=this;t.toggleClass(n.getEl().lastChild,n.classPrefix+"active",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"";return'
    '},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(e){var n=e.target;if(e.control==this)for(;n;){if("BUTTON"==n.nodeName&&-1==n.className.indexOf("open"))return e.stopImmediatePropagation(),void t.call(this,e);n=n.parentNode}}),delete e.settings.onclick,e._super()}})}),r(Yt,[Ht],function(e){return e.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"}})}),r(Gt,[K,W],function(e,t){return e.extend({lastIdx:0,Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(e){this.activeTabId&&t.removeClass(this.getEl(this.activeTabId),this.classPrefix+"active"),this.activeTabId="t"+e,t.addClass(this.getEl("t"+e),this.classPrefix+"active"),e!=this.lastIdx&&(this.items()[this.lastIdx].hide(),this.lastIdx=e),this.items()[e].show().fire("showtab"),this.reflow()},renderHtml:function(){var e=this,t=e._layout,n="",r=e.classPrefix;return e.preRender(),t.preRender(e),e.items().each(function(t,i){n+='
    '+e.encode(t.settings.title)+"
    "}),'
    '+n+'
    '+t.renderHtml(e)+"
    "},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on("click",function(t){var n=t.target.parentNode;if(t.target.parentNode.id==e._id+"-head")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,n,r,i;r=t.getSize(e.getEl("head")).width,r=0>r?0:r,i=0,e.items().each(function(t,n){r=Math.max(r,t.layoutRect().minW),i=Math.max(i,t.layoutRect().minH),e.settings.activeTab!=n&&t.hide()}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=r,e.settings.h=i,e.layoutRect({x:0,y:0,w:r,h:i})});var o=t.getSize(e.getEl("head")).height;return e.settings.minWidth=r,e.settings.minHeight=i+o,n=e._super(),n.deltaH+=o,n.innerH=n.h-n.deltaH,n}})}),r(Xt,[yt,W],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t._value=e.value||"",t.addClass("textbox"),e.multiline?t.addClass("multiline"):t.on("keydown",function(e){13==e.keyCode&&t.parents().reverse().each(function(t){return e.preventDefault(),t.hasEventListeners("submit")&&t.toJSON?(t.fire("submit",{data:t.toJSON()}),!1):void 0})})},disabled:function(e){var t=this;return t._rendered&&"undefined"!=typeof e&&(t.getEl().disabled=e),t._super(e)},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t._rendered&&(t.getEl().value=e),t):t._rendered?t.getEl().value:t._value},repaint:function(){var e=this,t,n,r,i=0,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+"px"),r=e._borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+"px",a.x=n.x),n.y!==a.y&&(t.top=n.y+"px",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+"px",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+"px",a.h=n.h),e._lastRepaintRect=a,e.fire("repaint",{},!1),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.encode(e._value,!1),i="";return"spellcheck"in n&&(i+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(i+=' maxlength="'+n.maxLength+'"'),n.size&&(i+=' size="'+n.size+'"'),n.subtype&&(i+=' type="'+n.subtype+'"'),e.disabled()&&(i+=' disabled="disabled"'),n.multiline?'":'"},postRender:function(){var e=this;return t.on(e.getEl(),"change",function(t){e.fire("change",t)}),e._super()},remove:function(){t.off(this.getEl()),this._super()}})}),r(Jt,[W],function(e){return function(t){var n=this,r;n.show=function(i){return n.hide(),r=!0,window.setTimeout(function(){r&&t.appendChild(e.createFragment('
    '))},i||0),n},n.hide=function(){var e=t.lastChild;return e&&-1!=e.className.indexOf("throbber")&&e.parentNode.removeChild(e),r=!1,n}}}),a([l,c,d,u,f,p,m,h,g,v,y,b,C,x,w,_,N,E,k,S,T,R,A,B,L,H,M,D,P,O,I,z,F,W,V,U,q,j,$,K,Y,G,X,J,Q,Z,et,tt,nt,rt,it,ot,at,st,lt,ct,dt,ut,ft,pt,mt,ht,gt,vt,yt,bt,Ct,xt,wt,_t,Nt,Et,kt,St,Tt,Rt,At,Bt,Lt,Ht,Mt,Dt,Pt,Ot,It,zt,Ft,Wt,Vt,Ut,qt,jt,$t,Kt,Yt,Gt,Xt,Jt])}(this); \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/xcharts/LICENSE b/plugins/web_gui/static/plugins/xcharts/LICENSE new file mode 100644 index 0000000..b5bdbb0 --- /dev/null +++ b/plugins/web_gui/static/plugins/xcharts/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2012 tenXer, Inc. + +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. diff --git a/plugins/web_gui/static/plugins/xcharts/README.md b/plugins/web_gui/static/plugins/xcharts/README.md new file mode 100644 index 0000000..6b9ff6e --- /dev/null +++ b/plugins/web_gui/static/plugins/xcharts/README.md @@ -0,0 +1,17 @@ +# xCharts [![Build Status](https://secure.travis-ci.org/tenXer/xcharts.png?branch=master)](http://travis-ci.org/tenxer/xcharts) + +[xCharts](http://tenxer.github.com/xcharts/) is a D3-based library for building custom charts and graphs. Written and maintained by [tenXer](https://www.tenxer.com). + +## Documentation + +View the [xCharts site](http://tenxer.github.com/xcharts/) for everything you need. + +## License + +Copyright (c) 2012 tenXer, Inc. + +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. diff --git a/plugins/web_gui/static/plugins/xcharts/xcharts.css b/plugins/web_gui/static/plugins/xcharts/xcharts.css new file mode 100644 index 0000000..8d8c760 --- /dev/null +++ b/plugins/web_gui/static/plugins/xcharts/xcharts.css @@ -0,0 +1,283 @@ +.xchart .line { + stroke-width: 3px; + fill: none; +} +.xchart .fill { + stroke-width: 0; +} +.xchart circle { + stroke: #FFF; + stroke-width: 3px; +} +.xchart .axis .domain { + fill: none; +} +.xchart .axis .tick line { + stroke: #EEE; + stroke-width: 1px; +} +.xchart .axis text { + font-family: Helvetica, Arial, Verdana, sans-serif; + fill: #666; + font-size: 12px; +} +.xchart .color0 .line { + stroke: #3880aa; +} +.xchart .color0 .line .fill { + pointer-events: none; +} +.xchart .color0 rect, +.xchart .color0 circle { + fill: #3880aa; +} +.xchart .color0 .fill { + fill: rgba(56, 128, 170, 0.1); +} +.xchart .color0.comp .line { + stroke: #89bbd8; +} +.xchart .color0.comp rect { + fill: #89bbd8; +} +.xchart .color0.comp .fill { + display: none; +} +.xchart .color0.comp circle, +.xchart .color0.comp .pointer { + fill: #89bbd8; +} +.xchart .color1 .line { + stroke: #4da944; +} +.xchart .color1 .line .fill { + pointer-events: none; +} +.xchart .color1 rect, +.xchart .color1 circle { + fill: #4da944; +} +.xchart .color1 .fill { + fill: rgba(77, 169, 68, 0.1); +} +.xchart .color1.comp .line { + stroke: #9dd597; +} +.xchart .color1.comp rect { + fill: #9dd597; +} +.xchart .color1.comp .fill { + display: none; +} +.xchart .color1.comp circle, +.xchart .color1.comp .pointer { + fill: #9dd597; +} +.xchart .color2 .line { + stroke: #f26522; +} +.xchart .color2 .line .fill { + pointer-events: none; +} +.xchart .color2 rect, +.xchart .color2 circle { + fill: #f26522; +} +.xchart .color2 .fill { + fill: rgba(242, 101, 34, 0.1); +} +.xchart .color2.comp .line { + stroke: #f9b99a; +} +.xchart .color2.comp rect { + fill: #f9b99a; +} +.xchart .color2.comp .fill { + display: none; +} +.xchart .color2.comp circle, +.xchart .color2.comp .pointer { + fill: #f9b99a; +} +.xchart .color3 .line { + stroke: #c6080d; +} +.xchart .color3 .line .fill { + pointer-events: none; +} +.xchart .color3 rect, +.xchart .color3 circle { + fill: #c6080d; +} +.xchart .color3 .fill { + fill: rgba(198, 8, 13, 0.1); +} +.xchart .color3.comp .line { + stroke: #f8555a; +} +.xchart .color3.comp rect { + fill: #f8555a; +} +.xchart .color3.comp .fill { + display: none; +} +.xchart .color3.comp circle, +.xchart .color3.comp .pointer { + fill: #f8555a; +} +.xchart .color4 .line { + stroke: #672d8b; +} +.xchart .color4 .line .fill { + pointer-events: none; +} +.xchart .color4 rect, +.xchart .color4 circle { + fill: #672d8b; +} +.xchart .color4 .fill { + fill: rgba(103, 45, 139, 0.1); +} +.xchart .color4.comp .line { + stroke: #a869ce; +} +.xchart .color4.comp rect { + fill: #a869ce; +} +.xchart .color4.comp .fill { + display: none; +} +.xchart .color4.comp circle, +.xchart .color4.comp .pointer { + fill: #a869ce; +} +.xchart .color5 .line { + stroke: #ce1797; +} +.xchart .color5 .line .fill { + pointer-events: none; +} +.xchart .color5 rect, +.xchart .color5 circle { + fill: #ce1797; +} +.xchart .color5 .fill { + fill: rgba(206, 23, 151, 0.1); +} +.xchart .color5.comp .line { + stroke: #f075cb; +} +.xchart .color5.comp rect { + fill: #f075cb; +} +.xchart .color5.comp .fill { + display: none; +} +.xchart .color5.comp circle, +.xchart .color5.comp .pointer { + fill: #f075cb; +} +.xchart .color6 .line { + stroke: #d9ce00; +} +.xchart .color6 .line .fill { + pointer-events: none; +} +.xchart .color6 rect, +.xchart .color6 circle { + fill: #d9ce00; +} +.xchart .color6 .fill { + fill: rgba(217, 206, 0, 0.1); +} +.xchart .color6.comp .line { + stroke: #fff75a; +} +.xchart .color6.comp rect { + fill: #fff75a; +} +.xchart .color6.comp .fill { + display: none; +} +.xchart .color6.comp circle, +.xchart .color6.comp .pointer { + fill: #fff75a; +} +.xchart .color7 .line { + stroke: #754c24; +} +.xchart .color7 .line .fill { + pointer-events: none; +} +.xchart .color7 rect, +.xchart .color7 circle { + fill: #754c24; +} +.xchart .color7 .fill { + fill: rgba(117, 76, 36, 0.1); +} +.xchart .color7.comp .line { + stroke: #c98c50; +} +.xchart .color7.comp rect { + fill: #c98c50; +} +.xchart .color7.comp .fill { + display: none; +} +.xchart .color7.comp circle, +.xchart .color7.comp .pointer { + fill: #c98c50; +} +.xchart .color8 .line { + stroke: #2eb9b4; +} +.xchart .color8 .line .fill { + pointer-events: none; +} +.xchart .color8 rect, +.xchart .color8 circle { + fill: #2eb9b4; +} +.xchart .color8 .fill { + fill: rgba(46, 185, 180, 0.1); +} +.xchart .color8.comp .line { + stroke: #86e1de; +} +.xchart .color8.comp rect { + fill: #86e1de; +} +.xchart .color8.comp .fill { + display: none; +} +.xchart .color8.comp circle, +.xchart .color8.comp .pointer { + fill: #86e1de; +} +.xchart .color9 .line { + stroke: #0e2e42; +} +.xchart .color9 .line .fill { + pointer-events: none; +} +.xchart .color9 rect, +.xchart .color9 circle { + fill: #0e2e42; +} +.xchart .color9 .fill { + fill: rgba(14, 46, 66, 0.1); +} +.xchart .color9.comp .line { + stroke: #2477ab; +} +.xchart .color9.comp rect { + fill: #2477ab; +} +.xchart .color9.comp .fill { + display: none; +} +.xchart .color9.comp circle, +.xchart .color9.comp .pointer { + fill: #2477ab; +} diff --git a/plugins/web_gui/static/plugins/xcharts/xcharts.js b/plugins/web_gui/static/plugins/xcharts/xcharts.js new file mode 100644 index 0000000..582407a --- /dev/null +++ b/plugins/web_gui/static/plugins/xcharts/xcharts.js @@ -0,0 +1,1158 @@ +/*! +xCharts v0.3.0 Copyright (c) 2012, tenXer, Inc. All Rights Reserved. +@license MIT license. http://github.com/tenXer/xcharts for details +*/ + +(function () { + +var xChart, + _vis = {}, + _scales = {}, + _visutils = {}; +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,v=e.reduce,h=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.3";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduce===v)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduceRight===h)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?-1!=n.indexOf(t):E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2);return w.map(n,function(n){return(w.isFunction(t)?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t){return w.isEmpty(t)?[]:w.filter(n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var F=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=F(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i};var I=function(){};w.bind=function(n,t){var r,e;if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));if(!w.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));I.prototype=n.prototype;var u=new I;I.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},w.bindAll=function(n){var t=o.call(arguments,1);return 0==t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=S(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&S(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return S(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),w.isFunction=function(n){return"function"==typeof n},w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return void 0===n},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+(0|Math.random()*(t-n+1))};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};T.unescape=w.invert(T.escape);var M={escape:RegExp("["+w.keys(T.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(T.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(M[n],function(t){return T[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=""+ ++N;return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){r=w.defaults({},r,w.templateSettings);var e=RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,a,o){return i+=n.slice(u,o).replace(D,function(n){return"\\"+B[n]}),r&&(i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(i+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),a&&(i+="';\n"+a+"\n__p+='"),u=o+t.length,t}),i+="';\n",r.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var a=Function(r.variable||"obj","_",i)}catch(o){throw o.source=i,o}if(t)return a(t,w);var c=function(n){return a.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+i+"}",c},w.chain=function(n){return w(n).chain()};var z=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);function getInsertionPoint(zIndex) { + return _.chain(_.range(zIndex, 10)).reverse().map(function (z) { + return 'g[data-index="' + z + '"]'; + }).value().join(', '); +} + +function colorClass(el, i) { + var c = el.getAttribute('class'); + return ((c !== null) ? c.replace(/color\d+/g, '') : '') + ' color' + i; +} + +_visutils = { + getInsertionPoint: getInsertionPoint, + colorClass: colorClass +}; +var local = this, + defaultSpacing = 0.25; + +function _getDomain(data, axis) { + return _.chain(data) + .pluck('data') + .flatten() + .pluck(axis) + .uniq() + .filter(function (d) { + return d !== undefined && d !== null; + }) + .value() + .sort(d3.ascending); +} + +_scales.ordinal = function (data, axis, bounds, extents) { + var domain = _getDomain(data, axis); + return d3.scale.ordinal() + .domain(domain) + .rangeRoundBands(bounds, defaultSpacing); +}; + +_scales.linear = function (data, axis, bounds, extents) { + return d3.scale.linear() + .domain(extents) + .nice() + .rangeRound(bounds); +}; + +_scales.exponential = function (data, axis, bounds, extents) { + return d3.scale.pow() + .exponent(0.65) + .domain(extents) + .nice() + .rangeRound(bounds); +}; + +_scales.time = function (data, axis, bounds, extents) { + return d3.time.scale() + .domain(_.map(extents, function (d) { return new Date(d); })) + .range(bounds); +}; + +function _extendDomain(domain, axis) { + var min = domain[0], + max = domain[1], + diff, + e; + + if (min === max) { + e = Math.max(Math.round(min / 10), 4); + min -= e; + max += e; + } + + diff = max - min; + min = (min) ? min - (diff / 10) : min; + min = (domain[0] > 0) ? Math.max(min, 0) : min; + max = (max) ? max + (diff / 10) : max; + max = (domain[1] < 0) ? Math.min(max, 0) : max; + + return [min, max]; +} + +function _getExtents(options, data, xType, yType) { + var extents, + nData = _.chain(data) + .pluck('data') + .flatten() + .value(); + + extents = { + x: d3.extent(nData, function (d) { return d.x; }), + y: d3.extent(nData, function (d) { return d.y; }) + }; + + _.each([xType, yType], function (type, i) { + var axis = (i) ? 'y' : 'x', + extended; + extents[axis] = d3.extent(nData, function (d) { return d[axis]; }); + if (type === 'ordinal') { + return; + } + + _.each([axis + 'Min', axis + 'Max'], function (minMax, i) { + if (type !== 'time') { + extended = _extendDomain(extents[axis]); + } + + if (options.hasOwnProperty(minMax) && options[minMax] !== null) { + extents[axis][i] = options[minMax]; + } else if (type !== 'time') { + extents[axis][i] = extended[i]; + } + }); + }); + + return extents; +} + +_scales.xy = function (self, data, xType, yType) { + var o = self._options, + extents = _getExtents(o, data, xType, yType), + scales = {}, + horiz = [o.axisPaddingLeft, self._width], + vert = [self._height, o.axisPaddingTop], + xScale, + yScale; + + _.each([xType, yType], function (type, i) { + var axis = (i === 0) ? 'x' : 'y', + bounds = (i === 0) ? horiz : vert, + fn = xChart.getScale(type); + scales[axis] = fn(data, axis, bounds, extents[axis]); + }); + + return scales; +}; +(function () { + var zIndex = 2, + selector = 'g.bar', + insertBefore = _visutils.getInsertionPoint(zIndex); + + function postUpdateScale(self, scaleData, mainData, compData) { + self.xScale2 = d3.scale.ordinal() + .domain(d3.range(0, mainData.length)) + .rangeRoundBands([0, self.xScale.rangeBand()], 0.08); + } + + function enter(self, storage, className, data, callbacks) { + var barGroups, bars, + yZero = self.yZero; + + barGroups = self._g.selectAll(selector + className) + .data(data, function (d) { + return d.className; + }); + + barGroups.enter().insert('g', insertBefore) + .attr('data-index', zIndex) + .style('opacity', 0) + .attr('class', function (d, i) { + var cl = _.uniq((className + d.className).split('.')).join(' '); + return cl + ' bar ' + _visutils.colorClass(this, i); + }) + .attr('transform', function (d, i) { + return 'translate(' + self.xScale2(i) + ',0)'; + }); + + bars = barGroups.selectAll('rect') + .data(function (d) { + return d.data; + }, function (d) { + return d.x; + }); + + bars.enter().append('rect') + .attr('width', 0) + .attr('rx', 3) + .attr('ry', 3) + .attr('x', function (d) { + return self.xScale(d.x) + (self.xScale2.rangeBand() / 2); + }) + .attr('height', function (d) { + return Math.abs(yZero - self.yScale(d.y)); + }) + .attr('y', function (d) { + return (d.y < 0) ? yZero : self.yScale(d.y); + }) + .on('mouseover', callbacks.mouseover) + .on('mouseout', callbacks.mouseout) + .on('click', callbacks.click); + + storage.barGroups = barGroups; + storage.bars = bars; + } + + function update(self, storage, timing) { + var yZero = self.yZero; + + storage.barGroups + .attr('class', function (d, i) { + return _visutils.colorClass(this, i); + }) + .transition().duration(timing) + .style('opacity', 1) + .attr('transform', function (d, i) { + return 'translate(' + self.xScale2(i) + ',0)'; + }); + + storage.bars.transition().duration(timing) + .attr('width', self.xScale2.rangeBand()) + .attr('x', function (d) { + return self.xScale(d.x); + }) + .attr('height', function (d) { + return Math.abs(yZero - self.yScale(d.y)); + }) + .attr('y', function (d) { + return (d.y < 0) ? yZero : self.yScale(d.y); + }); + } + + function exit(self, storage, timing) { + storage.bars.exit() + .transition().duration(timing) + .attr('width', 0) + .remove(); + storage.barGroups.exit() + .transition().duration(timing) + .style('opacity', 0) + .remove(); + } + + function destroy(self, storage, timing) { + var band = (self.xScale2) ? self.xScale2.rangeBand() / 2 : 0; + delete self.xScale2; + storage.bars + .transition().duration(timing) + .attr('width', 0) + .attr('x', function (d) { + return self.xScale(d.x) + band; + }); + } + + _vis.bar = { + postUpdateScale: postUpdateScale, + enter: enter, + update: update, + exit: exit, + destroy: destroy + }; +}()); +(function () { + + var zIndex = 3, + selector = 'g.line', + insertBefore = _visutils.getInsertionPoint(zIndex); + + function enter(self, storage, className, data, callbacks) { + var inter = self._options.interpolation, + x = function (d, i) { + if (!self.xScale2 && !self.xScale.rangeBand) { + return self.xScale(d.x); + } + return self.xScale(d.x) + (self.xScale.rangeBand() / 2); + }, + y = function (d) { return self.yScale(d.y); }, + line = d3.svg.line() + .x(x) + .interpolate(inter), + area = d3.svg.area() + .x(x) + .y1(self.yZero) + .interpolate(inter), + container, + fills, + paths; + + function datum(d) { + return [d.data]; + } + + container = self._g.selectAll(selector + className) + .data(data, function (d) { + return d.className; + }); + + container.enter().insert('g', insertBefore) + .attr('data-index', zIndex) + .attr('class', function (d, i) { + var cl = _.uniq((className + d.className).split('.')).join(' '); + return cl + ' line ' + _visutils.colorClass(this, i); + }); + + fills = container.selectAll('path.fill') + .data(datum); + + fills.enter().append('path') + .attr('class', 'fill') + .style('opacity', 0) + .attr('d', area.y0(y)); + + paths = container.selectAll('path.line') + .data(datum); + + paths.enter().append('path') + .attr('class', 'line') + .style('opacity', 0) + .attr('d', line.y(y)); + + storage.lineContainers = container; + storage.lineFills = fills; + storage.linePaths = paths; + storage.lineX = x; + storage.lineY = y; + storage.lineA = area; + storage.line = line; + } + + function update(self, storage, timing) { + storage.lineContainers + .attr('class', function (d, i) { + return _visutils.colorClass(this, i); + }); + + storage.lineFills.transition().duration(timing) + .style('opacity', 1) + .attr('d', storage.lineA.y0(storage.lineY)); + + storage.linePaths.transition().duration(timing) + .style('opacity', 1) + .attr('d', storage.line.y(storage.lineY)); + } + + function exit(self, storage) { + storage.linePaths.exit() + .style('opacity', 0) + .remove(); + storage.lineFills.exit() + .style('opacity', 0) + .remove(); + + storage.lineContainers.exit() + .remove(); + } + + function destroy(self, storage, timing) { + storage.linePaths.transition().duration(timing) + .style('opacity', 0); + storage.lineFills.transition().duration(timing) + .style('opacity', 0); + } + + _vis.line = { + enter: enter, + update: update, + exit: exit, + destroy: destroy + }; +}()); +(function () { + var line = _vis.line; + + function enter(self, storage, className, data, callbacks) { + var circles; + + line.enter(self, storage, className, data, callbacks); + + circles = storage.lineContainers.selectAll('circle') + .data(function (d) { + return d.data; + }, function (d) { + return d.x; + }); + + circles.enter().append('circle') + .style('opacity', 0) + .attr('cx', storage.lineX) + .attr('cy', storage.lineY) + .attr('r', 5) + .on('mouseover', callbacks.mouseover) + .on('mouseout', callbacks.mouseout) + .on('click', callbacks.click); + + storage.lineCircles = circles; + } + + function update(self, storage, timing) { + line.update.apply(null, _.toArray(arguments)); + + storage.lineCircles.transition().duration(timing) + .style('opacity', 1) + .attr('cx', storage.lineX) + .attr('cy', storage.lineY); + } + + function exit(self, storage) { + storage.lineCircles.exit() + .remove(); + line.exit.apply(null, _.toArray(arguments)); + } + + function destroy(self, storage, timing) { + line.destroy.apply(null, _.toArray(arguments)); + if (!storage.lineCircles) { + return; + } + storage.lineCircles.transition().duration(timing) + .style('opacity', 0); + } + + _vis['line-dotted'] = { + enter: enter, + update: update, + exit: exit, + destroy: destroy + }; +}()); +(function () { + var line = _vis['line-dotted']; + + function enter(self, storage, className, data, callbacks) { + line.enter(self, storage, className, data, callbacks); + } + + function _accumulate_data(data) { + function reduce(memo, num) { + return memo + num.y; + } + + var nData = _.map(data, function (set) { + var i = set.data.length, + d = _.clone(set.data); + set = _.clone(set); + while (i) { + i -= 1; + // Need to clone here, otherwise we are actually setting the same + // data onto the original data set. + d[i] = _.clone(set.data[i]); + d[i].y0 = set.data[i].y; + d[i].y = _.reduce(_.first(set.data, i), reduce, set.data[i].y); + } + return _.extend(set, { data: d }); + }); + + return nData; + } + + function _resetData(self) { + if (!self.hasOwnProperty('cumulativeOMainData')) { + return; + } + self._mainData = self.cumulativeOMainData; + delete self.cumulativeOMainData; + self._compData = self.cumulativeOCompData; + delete self.cumulativeOCompData; + } + + function preUpdateScale(self, data) { + _resetData(self); + self.cumulativeOMainData = self._mainData; + self._mainData = _accumulate_data(self._mainData); + self.cumulativeOCompData = self._compData; + self._compData = _accumulate_data(self._compData); + } + + function destroy(self, storage, timing) { + _resetData(self); + line.destroy.apply(null, _.toArray(arguments)); + } + + _vis.cumulative = { + preUpdateScale: preUpdateScale, + enter: enter, + update: line.update, + exit: line.exit, + destroy: destroy + }; +}()); +var emptyData = [[]], + defaults = { + // User interaction callbacks + mouseover: function (data, i) {}, + mouseout: function (data, i) {}, + click: function (data, i) {}, + + // Padding between the axes and the contents of the chart + axisPaddingTop: 0, + axisPaddingRight: 0, + axisPaddingBottom: 5, + axisPaddingLeft: 20, + + // Padding around the edge of the chart (space for axis labels, etc) + paddingTop: 0, + paddingRight: 0, + paddingBottom: 20, + paddingLeft: 60, + + // Axis tick formatting + tickHintX: 10, + tickFormatX: function (x) { return x; }, + tickHintY: 10, + tickFormatY: function (y) { return y; }, + + // Min/Max Axis Values + xMin: null, + xMax: null, + yMin: null, + yMax: null, + + // Pre-format input data + dataFormatX: function (x) { return x; }, + dataFormatY: function (y) { return y; }, + + unsupported: function (selector) { + d3.select(selector).text('SVG is not supported on your browser'); + }, + + // Callback functions if no data + empty: function (self, selector, d) {}, + notempty: function (self, selector) {}, + + timing: 750, + + // Line interpolation + interpolation: 'monotone', + + // Data sorting + sortX: function (a, b) { + return (!a.x && !b.x) ? 0 : (a.x < b.x) ? -1 : 1; + } + }; + +// What/how should the warning/error be presented? +function svgEnabled() { + var d = document; + return (!!d.createElementNS && + !!d.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect); +} + +/** + * Creates a new chart + * + * @param string type The drawing type for the main data + * @param array data Data to render in the chart + * @param string selector CSS Selector for the parent element for the chart + * @param object options Optional. See `defaults` for options + * + * Examples: + * var data = { + * "main": [ + * { + * "data": [ + * { + * "x": "2012-08-09T07:00:00.522Z", + * "y": 68 + * }, + * { + * "x": "2012-08-10T07:00:00.522Z", + * "y": 295 + * }, + * { + * "x": "2012-08-11T07:00:00.522Z", + * "y": 339 + * }, + * ], + * "className": ".foo" + * } + * ], + * "xScale": "ordinal", + * "yScale": "linear", + * "comp": [ + * { + * "data": [ + * { + * "x": "2012-08-09T07:00:00.522Z", + * "y": 288 + * }, + * { + * "x": "2012-08-10T07:00:00.522Z", + * "y": 407 + * }, + * { + * "x": "2012-08-11T07:00:00.522Z", + * "y": 459 + * } + * ], + * "className": ".comp.comp_foo", + * "type": "line-arrowed" + * } + * ] + * }, + * myChart = new Chart('bar', data, '#chart'); + * + */ +function xChart(type, data, selector, options) { + var self = this, + resizeLock; + + self._options = options = _.defaults(options || {}, defaults); + + if (svgEnabled() === false) { + return options.unsupported(selector); + } + + self._selector = selector; + self._container = d3.select(selector); + self._drawSvg(); + self._mainStorage = {}; + self._compStorage = {}; + + data = _.clone(data); + if (type && !data.type) { + data.type = type; + } + + self.setData(data); + + d3.select(window).on('resize.for.' + selector, function () { + if (resizeLock) { + clearTimeout(resizeLock); + } + resizeLock = setTimeout(function () { + resizeLock = null; + self._resize(); + }, 500); + }); +} + +/** + * Add a visualization type + * + * @param string type Unique key/name used with setType + * @param object vis object map of vis methods + */ +xChart.setVis = function (type, vis) { + if (_vis.hasOwnProperty(type)) { + throw 'Cannot override vis type "' + type + '".'; + } + _vis[type] = vis; +}; + +/** + * Get a clone of a visualization + * Useful for extending vis functionality + * + * @param string type Unique key/name of the vis + */ +xChart.getVis = function (type) { + if (!_vis.hasOwnProperty(type)) { + throw 'Vis type "' + type + '" does not exist.'; + } + + return _.clone(_vis[type]); +}; + +xChart.setScale = function (name, fn) { + if (_scales.hasOwnProperty(name)) { + throw 'Scale type "' + name + '" already exists.'; + } + + _scales[name] = fn; +}; + +xChart.getScale = function (name) { + if (!_scales.hasOwnProperty(name)) { + throw 'Scale type "' + name + '" does not exist.'; + } + return _scales[name]; +}; + +xChart.visutils = _visutils; + +_.defaults(xChart.prototype, { + /** + * Set or change the drawing type for the main data. + * + * @param string type Must be an available drawing type + * + */ + setType: function (type, skipDraw) { + var self = this; + + if (self._type && type === self._type) { + return; + } + + if (!_vis.hasOwnProperty(type)) { + throw 'Vis type "' + type + '" is not defined.'; + } + + if (self._type) { + self._destroy(self._vis, self._mainStorage); + } + + self._type = type; + self._vis = _vis[type]; + if (!skipDraw) { + self._draw(); + } + }, + + /** + * Set and update the data for the chart. Optionally skip drawing. + * + * @param object data New data. See new xChart example for format + * + */ + setData: function (data) { + var self = this, + o = self._options, + nData = _.clone(data); + + if (!data.hasOwnProperty('main')) { + throw 'No "main" key found in given chart data.'; + } + + switch (data.type) { + case 'bar': + // force the xScale to be ordinal + data.xScale = 'ordinal'; + break; + case undefined: + data.type = self._type; + break; + } + + o.xMin = (isNaN(parseInt(data.xMin, 10))) ? o.xMin : data.xMin; + o.xMax = (isNaN(parseInt(data.xMax, 10))) ? o.xMax : data.xMax; + o.yMin = (isNaN(parseInt(data.yMin, 10))) ? o.yMin : data.yMin; + o.yMax = (isNaN(parseInt(data.yMax, 10))) ? o.yMax : data.yMax; + + if (self._vis) { + self._destroy(self._vis, self._mainStorage); + } + + self.setType(data.type, true); + + function _mapData(set) { + var d = _.map(_.clone(set.data), function (p) { + var np = _.clone(p); + if (p.hasOwnProperty('x')) { + np.x = o.dataFormatX(p.x); + } + if (p.hasOwnProperty('y')) { + np.y = o.dataFormatY(p.y); + } + return np; + }).sort(o.sortX); + return _.extend(_.clone(set), { data: d }); + } + + nData.main = _.map(nData.main, _mapData); + self._mainData = nData.main; + self._xScaleType = nData.xScale; + self._yScaleType = nData.yScale; + + if (nData.hasOwnProperty('comp')) { + nData.comp = _.map(nData.comp, _mapData); + self._compData = nData.comp; + } else { + self._compData = []; + } + + self._draw(); + }, + + /** + * Change the scale of an axis + * + * @param string axis Name of an axis. One of 'x' or 'y' + * @param string type Name of the scale type + * + */ + setScale: function (axis, type) { + var self = this; + + switch (axis) { + case 'x': + self._xScaleType = type; + break; + case 'y': + self._yScaleType = type; + break; + default: + throw 'Cannot change scale of unknown axis "' + axis + '".'; + } + + self._draw(); + }, + + /** + * Create the SVG element and g container. Resize if necessary. + */ + _drawSvg: function () { + var self = this, + c = self._container, + options = self._options, + width = parseInt(c.style('width').replace('px', ''), 10), + height = parseInt(c.style('height').replace('px', ''), 10), + svg, + g, + gScale; + + svg = c.selectAll('svg') + .data(emptyData); + + svg.enter().append('svg') + // Inherit the height and width from the parent element + .attr('height', height) + .attr('width', width) + .attr('class', 'xchart'); + + svg.transition() + .attr('width', width) + .attr('height', height); + + g = svg.selectAll('g') + .data(emptyData); + + g.enter().append('g') + .attr( + 'transform', + 'translate(' + options.paddingLeft + ',' + options.paddingTop + ')' + ); + + gScale = g.selectAll('g.scale') + .data(emptyData); + + gScale.enter().append('g') + .attr('class', 'scale'); + + self._svg = svg; + self._g = g; + self._gScale = gScale; + + self._height = height - options.paddingTop - options.paddingBottom - + options.axisPaddingTop - options.axisPaddingBottom; + self._width = width - options.paddingLeft - options.paddingRight - + options.axisPaddingLeft - options.axisPaddingRight; + }, + + /** + * Resize the visualization + */ + _resize: function (event) { + var self = this; + + self._drawSvg(); + self._draw(); + }, + + /** + * Draw the x and y axes + */ + _drawAxes: function () { + if (this._noData) { + return; + } + var self = this, + o = self._options, + t = self._gScale.transition().duration(o.timing), + xTicks = o.tickHintX, + yTicks = o.tickHintY, + bottom = self._height + o.axisPaddingTop + o.axisPaddingBottom, + zeroLine = d3.svg.line().x(function (d) { return d; }), + zLine, + zLinePath, + xAxis, + xRules, + yAxis, + yRules, + labels; + + xRules = d3.svg.axis() + .scale(self.xScale) + .ticks(xTicks) + .tickSize(-self._height) + .tickFormat(o.tickFormatX) + .orient('bottom'); + + xAxis = self._gScale.selectAll('g.axisX') + .data(emptyData); + + xAxis.enter().append('g') + .attr('class', 'axis axisX') + .attr('transform', 'translate(0,' + bottom + ')'); + + xAxis.call(xRules); + + labels = self._gScale.selectAll('.axisX g')[0]; + if (labels.length > (self._width / 80)) { + labels.sort(function (a, b) { + var r = /translate\(([^,)]+)/; + a = a.getAttribute('transform').match(r); + b = b.getAttribute('transform').match(r); + return parseFloat(a[1], 10) - parseFloat(b[1], 10); + }); + + d3.selectAll(labels) + .filter(function (d, i) { + return i % (Math.ceil(labels.length / xTicks) + 1); + }) + .remove(); + } + + yRules = d3.svg.axis() + .scale(self.yScale) + .ticks(yTicks) + .tickSize(-self._width - o.axisPaddingRight - o.axisPaddingLeft) + .tickFormat(o.tickFormatY) + .orient('left'); + + yAxis = self._gScale.selectAll('g.axisY') + .data(emptyData); + + yAxis.enter().append('g') + .attr('class', 'axis axisY') + .attr('transform', 'translate(0,0)'); + + t.selectAll('g.axisY') + .call(yRules); + + // zero line + zLine = self._gScale.selectAll('g.axisZero') + .data([[]]); + + zLine.enter().append('g') + .attr('class', 'axisZero'); + + zLinePath = zLine.selectAll('line') + .data([[]]); + + zLinePath.enter().append('line') + .attr('x1', 0) + .attr('x2', self._width + o.axisPaddingLeft + o.axisPaddingRight) + .attr('y1', self.yZero) + .attr('y2', self.yZero); + + zLinePath.transition().duration(o.timing) + .attr('y1', self.yZero) + .attr('y2', self.yZero); + }, + + /** + * Update the x and y scales (used when drawing) + * + * Optional methods in drawing types: + * preUpdateScale + * postUpdateScale + * + * Example implementation in vis type: + * + * function postUpdateScale(self, scaleData, mainData, compData) { + * self.xScale2 = d3.scale.ordinal() + * .domain(d3.range(0, mainData.length)) + * .rangeRoundBands([0, self.xScale.rangeBand()], 0.08); + * } + * + */ + _updateScale: function () { + var self = this, + _unionData = function () { + return _.union(self._mainData, self._compData); + }, + scaleData = _unionData(), + vis = self._vis, + scale, + min; + + delete self.xScale; + delete self.yScale; + delete self.yZero; + + if (vis.hasOwnProperty('preUpdateScale')) { + vis.preUpdateScale(self, scaleData, self._mainData, self._compData); + } + + // Just in case preUpdateScale modified + scaleData = _unionData(); + scale = _scales.xy(self, scaleData, self._xScaleType, self._yScaleType); + + self.xScale = scale.x; + self.yScale = scale.y; + + min = self.yScale.domain()[0]; + self.yZero = (min > 0) ? self.yScale(min) : self.yScale(0); + + if (vis.hasOwnProperty('postUpdateScale')) { + vis.postUpdateScale(self, scaleData, self._mainData, self._compData); + } + }, + + /** + * Create (Enter) the elements for the vis + * + * Required method + * + * Example implementation in vis type: + * + * function enter(self, data, callbacks) { + * var foo = self._g.selectAll('g.foobar') + * .data(data); + * foo.enter().append('g') + * .attr('class', 'foobar'); + * self.foo = foo; + * } + */ + _enter: function (vis, storage, data, className) { + var self = this, + callbacks = { + click: self._options.click, + mouseover: self._options.mouseover, + mouseout: self._options.mouseout + }; + self._checkVisMethod(vis, 'enter'); + vis.enter(self, storage, className, data, callbacks); + }, + + /** + * Update the elements opened by the select method + * + * Required method + * + * Example implementation in vis type: + * + * function update(self, timing) { + * self.bars.transition().duration(timing) + * .attr('width', self.xScale2.rangeBand()) + * .attr('height', function (d) { + * return self.yScale(d.y); + * }); + * } + */ + _update: function (vis, storage) { + var self = this; + self._checkVisMethod(vis, 'update'); + vis.update(self, storage, self._options.timing); + }, + + /** + * Remove or transition out the elements that no longer have data + * + * Required method + * + * Example implementation in vis type: + * + * function exit(self) { + * self.bars.exit().remove(); + * } + */ + _exit: function (vis, storage) { + var self = this; + self._checkVisMethod(vis, 'exit'); + vis.exit(self, storage, self._options.timing); + }, + + /** + * Destroy the current vis type (transition to new type) + * + * Required method + * + * Example implementation in vis type: + * + * function destroy(self, timing) { + * self.bars.transition().duration(timing) + * attr('height', 0); + * delete self.bars; + * } + */ + _destroy: function (vis, storage) { + var self = this; + self._checkVisMethod(vis, 'destroy'); + try { + vis.destroy(self, storage, self._options.timing); + } catch (e) {} + }, + + /** + * Draw the visualization + */ + _draw: function () { + var self = this, + o = self._options, + comp, + compKeys; + + self._noData = _.flatten(_.pluck(self._mainData, 'data') + .concat(_.pluck(self._compData, 'data'))).length === 0; + + self._updateScale(); + self._drawAxes(); + + self._enter(self._vis, self._mainStorage, self._mainData, '.main'); + self._exit(self._vis, self._mainStorage); + self._update(self._vis, self._mainStorage); + + comp = _.chain(self._compData).groupBy(function (d) { + return d.type; + }); + compKeys = comp.keys(); + + // Find old comp vis items and remove any that no longer exist + _.each(self._compStorage, function (d, key) { + if (-1 === compKeys.indexOf(key).value()) { + var vis = _vis[key]; + self._enter(vis, d, [], '.comp.' + key.replace(/\W+/g, '')); + self._exit(vis, d); + } + }); + + comp.each(function (d, key) { + var vis = _vis[key], storage; + if (!self._compStorage.hasOwnProperty(key)) { + self._compStorage[key] = {}; + } + storage = self._compStorage[key]; + self._enter(vis, storage, d, '.comp.' + key.replace(/\W+/g, '')); + self._exit(vis, storage); + self._update(vis, storage); + }); + + if (self._noData) { + o.empty(self, self._selector, self._mainData); + } else { + o.notempty(self, self._selector); + } + }, + + /** + * Ensure drawing method exists + */ + _checkVisMethod: function (vis, method) { + var self = this; + if (!vis[method]) { + throw 'Required method "' + method + '" not found on vis type "' + + self._type + '".'; + } + } +}); +if (typeof define === 'function' && define.amd && typeof define.amd === 'object') { + define(function () { + return xChart; + }); + return; +} + +window.xChart = xChart; + +}()); diff --git a/plugins/web_gui/static/plugins/xcharts/xcharts.min.css b/plugins/web_gui/static/plugins/xcharts/xcharts.min.css new file mode 100644 index 0000000..d5912ea --- /dev/null +++ b/plugins/web_gui/static/plugins/xcharts/xcharts.min.css @@ -0,0 +1 @@ +.xchart .line{stroke-width:3px;fill:none}.xchart .fill{stroke-width:0}.xchart circle{stroke:#FFF;stroke-width:3px}.xchart .axis .domain{fill:none}.xchart .axis .tick line{stroke:#EEE;stroke-width:1px}.xchart .axis text{font-family:Helvetica,Arial,Verdana,sans-serif;fill:#666;font-size:12px}.xchart .color0 .line{stroke:#3880aa}.xchart .color0 .line .fill{pointer-events:none}.xchart .color0 rect,.xchart .color0 circle{fill:#3880aa}.xchart .color0 .fill{fill:rgba(56,128,170,0.1)}.xchart .color0.comp .line{stroke:#89bbd8}.xchart .color0.comp rect{fill:#89bbd8}.xchart .color0.comp .fill{display:none}.xchart .color0.comp circle,.xchart .color0.comp .pointer{fill:#89bbd8}.xchart .color1 .line{stroke:#4da944}.xchart .color1 .line .fill{pointer-events:none}.xchart .color1 rect,.xchart .color1 circle{fill:#4da944}.xchart .color1 .fill{fill:rgba(77,169,68,0.1)}.xchart .color1.comp .line{stroke:#9dd597}.xchart .color1.comp rect{fill:#9dd597}.xchart .color1.comp .fill{display:none}.xchart .color1.comp circle,.xchart .color1.comp .pointer{fill:#9dd597}.xchart .color2 .line{stroke:#f26522}.xchart .color2 .line .fill{pointer-events:none}.xchart .color2 rect,.xchart .color2 circle{fill:#f26522}.xchart .color2 .fill{fill:rgba(242,101,34,0.1)}.xchart .color2.comp .line{stroke:#f9b99a}.xchart .color2.comp rect{fill:#f9b99a}.xchart .color2.comp .fill{display:none}.xchart .color2.comp circle,.xchart .color2.comp .pointer{fill:#f9b99a}.xchart .color3 .line{stroke:#c6080d}.xchart .color3 .line .fill{pointer-events:none}.xchart .color3 rect,.xchart .color3 circle{fill:#c6080d}.xchart .color3 .fill{fill:rgba(198,8,13,0.1)}.xchart .color3.comp .line{stroke:#f8555a}.xchart .color3.comp rect{fill:#f8555a}.xchart .color3.comp .fill{display:none}.xchart .color3.comp circle,.xchart .color3.comp .pointer{fill:#f8555a}.xchart .color4 .line{stroke:#672d8b}.xchart .color4 .line .fill{pointer-events:none}.xchart .color4 rect,.xchart .color4 circle{fill:#672d8b}.xchart .color4 .fill{fill:rgba(103,45,139,0.1)}.xchart .color4.comp .line{stroke:#a869ce}.xchart .color4.comp rect{fill:#a869ce}.xchart .color4.comp .fill{display:none}.xchart .color4.comp circle,.xchart .color4.comp .pointer{fill:#a869ce}.xchart .color5 .line{stroke:#ce1797}.xchart .color5 .line .fill{pointer-events:none}.xchart .color5 rect,.xchart .color5 circle{fill:#ce1797}.xchart .color5 .fill{fill:rgba(206,23,151,0.1)}.xchart .color5.comp .line{stroke:#f075cb}.xchart .color5.comp rect{fill:#f075cb}.xchart .color5.comp .fill{display:none}.xchart .color5.comp circle,.xchart .color5.comp .pointer{fill:#f075cb}.xchart .color6 .line{stroke:#d9ce00}.xchart .color6 .line .fill{pointer-events:none}.xchart .color6 rect,.xchart .color6 circle{fill:#d9ce00}.xchart .color6 .fill{fill:rgba(217,206,0,0.1)}.xchart .color6.comp .line{stroke:#fff75a}.xchart .color6.comp rect{fill:#fff75a}.xchart .color6.comp .fill{display:none}.xchart .color6.comp circle,.xchart .color6.comp .pointer{fill:#fff75a}.xchart .color7 .line{stroke:#754c24}.xchart .color7 .line .fill{pointer-events:none}.xchart .color7 rect,.xchart .color7 circle{fill:#754c24}.xchart .color7 .fill{fill:rgba(117,76,36,0.1)}.xchart .color7.comp .line{stroke:#c98c50}.xchart .color7.comp rect{fill:#c98c50}.xchart .color7.comp .fill{display:none}.xchart .color7.comp circle,.xchart .color7.comp .pointer{fill:#c98c50}.xchart .color8 .line{stroke:#2eb9b4}.xchart .color8 .line .fill{pointer-events:none}.xchart .color8 rect,.xchart .color8 circle{fill:#2eb9b4}.xchart .color8 .fill{fill:rgba(46,185,180,0.1)}.xchart .color8.comp .line{stroke:#86e1de}.xchart .color8.comp rect{fill:#86e1de}.xchart .color8.comp .fill{display:none}.xchart .color8.comp circle,.xchart .color8.comp .pointer{fill:#86e1de}.xchart .color9 .line{stroke:#0e2e42}.xchart .color9 .line .fill{pointer-events:none}.xchart .color9 rect,.xchart .color9 circle{fill:#0e2e42}.xchart .color9 .fill{fill:rgba(14,46,66,0.1)}.xchart .color9.comp .line{stroke:#2477ab}.xchart .color9.comp rect{fill:#2477ab}.xchart .color9.comp .fill{display:none}.xchart .color9.comp circle,.xchart .color9.comp .pointer{fill:#2477ab} \ No newline at end of file diff --git a/plugins/web_gui/static/plugins/xcharts/xcharts.min.js b/plugins/web_gui/static/plugins/xcharts/xcharts.min.js new file mode 100644 index 0000000..4788a98 --- /dev/null +++ b/plugins/web_gui/static/plugins/xcharts/xcharts.min.js @@ -0,0 +1,5 @@ +/*! +xCharts v0.3.0 Copyright (c) 2012, tenXer, Inc. All Rights Reserved. +@license MIT license. http://github.com/tenXer/xcharts for details +*/ +(function(){var xChart,_vis={},_scales={},_visutils={};(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,v=e.reduce,h=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.3";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduce===v)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduceRight===h)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?-1!=n.indexOf(t):E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2);return w.map(n,function(n){return(w.isFunction(t)?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t){return w.isEmpty(t)?[]:w.filter(n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var F=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=F(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i};var I=function(){};w.bind=function(n,t){var r,e;if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));if(!w.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));I.prototype=n.prototype;var u=new I;I.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},w.bindAll=function(n){var t=o.call(arguments,1);return 0==t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=S(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&S(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return S(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),w.isFunction=function(n){return"function"==typeof n},w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return void 0===n},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+(0|Math.random()*(t-n+1))};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};T.unescape=w.invert(T.escape);var M={escape:RegExp("["+w.keys(T.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(T.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(M[n],function(t){return T[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=""+ ++N;return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){r=w.defaults({},r,w.templateSettings);var e=RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,a,o){return i+=n.slice(u,o).replace(D,function(n){return"\\"+B[n]}),r&&(i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(i+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),a&&(i+="';\n"+a+"\n__p+='"),u=o+t.length,t}),i+="';\n",r.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var a=Function(r.variable||"obj","_",i)}catch(o){throw o.source=i,o}if(t)return a(t,w);var c=function(n){return a.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+i+"}",c},w.chain=function(n){return w(n).chain()};var z=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);function getInsertionPoint(zIndex){return _.chain(_.range(zIndex,10)).reverse().map(function(z){return'g[data-index="'+z+'"]'}).value().join(", ")}function colorClass(el,i){var c=el.getAttribute("class");return(c!==null?c.replace(/color\d+/g,""):"")+" color"+i}_visutils={getInsertionPoint:getInsertionPoint,colorClass:colorClass};var local=this,defaultSpacing=.25;function _getDomain(data,axis){return _.chain(data).pluck("data").flatten().pluck(axis).uniq().filter(function(d){return d!==undefined&&d!==null}).value().sort(d3.ascending)}_scales.ordinal=function(data,axis,bounds,extents){var domain=_getDomain(data,axis);return d3.scale.ordinal().domain(domain).rangeRoundBands(bounds,defaultSpacing)};_scales.linear=function(data,axis,bounds,extents){return d3.scale.linear().domain(extents).nice().rangeRound(bounds)};_scales.exponential=function(data,axis,bounds,extents){return d3.scale.pow().exponent(.65).domain(extents).nice().rangeRound(bounds)};_scales.time=function(data,axis,bounds,extents){return d3.time.scale().domain(_.map(extents,function(d){return new Date(d)})).range(bounds)};function _extendDomain(domain,axis){var min=domain[0],max=domain[1],diff,e;if(min===max){e=Math.max(Math.round(min/10),4);min-=e;max+=e}diff=max-min;min=min?min-diff/10:min;min=domain[0]>0?Math.max(min,0):min;max=max?max+diff/10:max;max=domain[1]<0?Math.min(max,0):max;return[min,max]}function _getExtents(options,data,xType,yType){var extents,nData=_.chain(data).pluck("data").flatten().value();extents={x:d3.extent(nData,function(d){return d.x}),y:d3.extent(nData,function(d){return d.y})};_.each([xType,yType],function(type,i){var axis=i?"y":"x",extended;extents[axis]=d3.extent(nData,function(d){return d[axis]});if(type==="ordinal"){return}_.each([axis+"Min",axis+"Max"],function(minMax,i){if(type!=="time"){extended=_extendDomain(extents[axis])}if(options.hasOwnProperty(minMax)&&options[minMax]!==null){extents[axis][i]=options[minMax]}else if(type!=="time"){extents[axis][i]=extended[i]}})});return extents}_scales.xy=function(self,data,xType,yType){var o=self._options,extents=_getExtents(o,data,xType,yType),scales={},horiz=[o.axisPaddingLeft,self._width],vert=[self._height,o.axisPaddingTop],xScale,yScale;_.each([xType,yType],function(type,i){var axis=i===0?"x":"y",bounds=i===0?horiz:vert,fn=xChart.getScale(type);scales[axis]=fn(data,axis,bounds,extents[axis])});return scales};(function(){var zIndex=2,selector="g.bar",insertBefore=_visutils.getInsertionPoint(zIndex);function postUpdateScale(self,scaleData,mainData,compData){self.xScale2=d3.scale.ordinal().domain(d3.range(0,mainData.length)).rangeRoundBands([0,self.xScale.rangeBand()],.08)}function enter(self,storage,className,data,callbacks){var barGroups,bars,yZero=self.yZero;barGroups=self._g.selectAll(selector+className).data(data,function(d){return d.className});barGroups.enter().insert("g",insertBefore).attr("data-index",zIndex).style("opacity",0).attr("class",function(d,i){var cl=_.uniq((className+d.className).split(".")).join(" ");return cl+" bar "+_visutils.colorClass(this,i)}).attr("transform",function(d,i){return"translate("+self.xScale2(i)+",0)"});bars=barGroups.selectAll("rect").data(function(d){return d.data},function(d){return d.x});bars.enter().append("rect").attr("width",0).attr("rx",3).attr("ry",3).attr("x",function(d){return self.xScale(d.x)+self.xScale2.rangeBand()/2}).attr("height",function(d){return Math.abs(yZero-self.yScale(d.y))}).attr("y",function(d){return d.y<0?yZero:self.yScale(d.y)}).on("mouseover",callbacks.mouseover).on("mouseout",callbacks.mouseout).on("click",callbacks.click);storage.barGroups=barGroups;storage.bars=bars}function update(self,storage,timing){var yZero=self.yZero;storage.barGroups.attr("class",function(d,i){return _visutils.colorClass(this,i)}).transition().duration(timing).style("opacity",1).attr("transform",function(d,i){return"translate("+self.xScale2(i)+",0)"});storage.bars.transition().duration(timing).attr("width",self.xScale2.rangeBand()).attr("x",function(d){return self.xScale(d.x)}).attr("height",function(d){return Math.abs(yZero-self.yScale(d.y))}).attr("y",function(d){return d.y<0?yZero:self.yScale(d.y)})}function exit(self,storage,timing){storage.bars.exit().transition().duration(timing).attr("width",0).remove();storage.barGroups.exit().transition().duration(timing).style("opacity",0).remove()}function destroy(self,storage,timing){var band=self.xScale2?self.xScale2.rangeBand()/2:0;delete self.xScale2;storage.bars.transition().duration(timing).attr("width",0).attr("x",function(d){return self.xScale(d.x)+band})}_vis.bar={postUpdateScale:postUpdateScale,enter:enter,update:update,exit:exit,destroy:destroy}})();(function(){var zIndex=3,selector="g.line",insertBefore=_visutils.getInsertionPoint(zIndex);function enter(self,storage,className,data,callbacks){var inter=self._options.interpolation,x=function(d,i){if(!self.xScale2&&!self.xScale.rangeBand){return self.xScale(d.x)}return self.xScale(d.x)+self.xScale.rangeBand()/2},y=function(d){return self.yScale(d.y)},line=d3.svg.line().x(x).interpolate(inter),area=d3.svg.area().x(x).y1(self.yZero).interpolate(inter),container,fills,paths;function datum(d){return[d.data]}container=self._g.selectAll(selector+className).data(data,function(d){return d.className});container.enter().insert("g",insertBefore).attr("data-index",zIndex).attr("class",function(d,i){var cl=_.uniq((className+d.className).split(".")).join(" ");return cl+" line "+_visutils.colorClass(this,i)});fills=container.selectAll("path.fill").data(datum);fills.enter().append("path").attr("class","fill").style("opacity",0).attr("d",area.y0(y));paths=container.selectAll("path.line").data(datum);paths.enter().append("path").attr("class","line").style("opacity",0).attr("d",line.y(y));storage.lineContainers=container;storage.lineFills=fills;storage.linePaths=paths;storage.lineX=x;storage.lineY=y;storage.lineA=area;storage.line=line}function update(self,storage,timing){storage.lineContainers.attr("class",function(d,i){return _visutils.colorClass(this,i)});storage.lineFills.transition().duration(timing).style("opacity",1).attr("d",storage.lineA.y0(storage.lineY));storage.linePaths.transition().duration(timing).style("opacity",1).attr("d",storage.line.y(storage.lineY))}function exit(self,storage){storage.linePaths.exit().style("opacity",0).remove();storage.lineFills.exit().style("opacity",0).remove();storage.lineContainers.exit().remove()}function destroy(self,storage,timing){storage.linePaths.transition().duration(timing).style("opacity",0);storage.lineFills.transition().duration(timing).style("opacity",0)}_vis.line={enter:enter,update:update,exit:exit,destroy:destroy}})();(function(){var line=_vis.line;function enter(self,storage,className,data,callbacks){var circles;line.enter(self,storage,className,data,callbacks);circles=storage.lineContainers.selectAll("circle").data(function(d){return d.data},function(d){return d.x});circles.enter().append("circle").style("opacity",0).attr("cx",storage.lineX).attr("cy",storage.lineY).attr("r",5).on("mouseover",callbacks.mouseover).on("mouseout",callbacks.mouseout).on("click",callbacks.click);storage.lineCircles=circles}function update(self,storage,timing){line.update.apply(null,_.toArray(arguments));storage.lineCircles.transition().duration(timing).style("opacity",1).attr("cx",storage.lineX).attr("cy",storage.lineY)}function exit(self,storage){storage.lineCircles.exit().remove();line.exit.apply(null,_.toArray(arguments))}function destroy(self,storage,timing){line.destroy.apply(null,_.toArray(arguments));if(!storage.lineCircles){return}storage.lineCircles.transition().duration(timing).style("opacity",0)}_vis["line-dotted"]={enter:enter,update:update,exit:exit,destroy:destroy}})();(function(){var line=_vis["line-dotted"];function enter(self,storage,className,data,callbacks){line.enter(self,storage,className,data,callbacks)}function _accumulate_data(data){function reduce(memo,num){return memo+num.y}var nData=_.map(data,function(set){var i=set.data.length,d=_.clone(set.data);set=_.clone(set);while(i){i-=1;d[i]=_.clone(set.data[i]);d[i].y0=set.data[i].y;d[i].y=_.reduce(_.first(set.data,i),reduce,set.data[i].y)}return _.extend(set,{data:d})});return nData}function _resetData(self){if(!self.hasOwnProperty("cumulativeOMainData")){return}self._mainData=self.cumulativeOMainData;delete self.cumulativeOMainData;self._compData=self.cumulativeOCompData;delete self.cumulativeOCompData}function preUpdateScale(self,data){_resetData(self);self.cumulativeOMainData=self._mainData;self._mainData=_accumulate_data(self._mainData);self.cumulativeOCompData=self._compData;self._compData=_accumulate_data(self._compData)}function destroy(self,storage,timing){_resetData(self);line.destroy.apply(null,_.toArray(arguments))}_vis.cumulative={preUpdateScale:preUpdateScale,enter:enter,update:line.update,exit:line.exit,destroy:destroy}})();var emptyData=[[]],defaults={mouseover:function(data,i){},mouseout:function(data,i){},click:function(data,i){},axisPaddingTop:0,axisPaddingRight:0,axisPaddingBottom:5,axisPaddingLeft:20,paddingTop:0,paddingRight:0,paddingBottom:20,paddingLeft:60,tickHintX:10,tickFormatX:function(x){return x},tickHintY:10,tickFormatY:function(y){return y},xMin:null,xMax:null,yMin:null,yMax:null,dataFormatX:function(x){return x},dataFormatY:function(y){return y},unsupported:function(selector){d3.select(selector).text("SVG is not supported on your browser")},empty:function(self,selector,d){},notempty:function(self,selector){},timing:750,interpolation:"monotone",sortX:function(a,b){return!a.x&&!b.x?0:a.xself._width/80){labels.sort(function(a,b){var r=/translate\(([^,)]+)/;a=a.getAttribute("transform").match(r);b=b.getAttribute("transform").match(r);return parseFloat(a[1],10)-parseFloat(b[1],10)});d3.selectAll(labels).filter(function(d,i){return i%(Math.ceil(labels.length/xTicks)+1)}).remove()}yRules=d3.svg.axis().scale(self.yScale).ticks(yTicks).tickSize(-self._width-o.axisPaddingRight-o.axisPaddingLeft).tickFormat(o.tickFormatY).orient("left");yAxis=self._gScale.selectAll("g.axisY").data(emptyData);yAxis.enter().append("g").attr("class","axis axisY").attr("transform","translate(0,0)");t.selectAll("g.axisY").call(yRules);zLine=self._gScale.selectAll("g.axisZero").data([[]]);zLine.enter().append("g").attr("class","axisZero");zLinePath=zLine.selectAll("line").data([[]]);zLinePath.enter().append("line").attr("x1",0).attr("x2",self._width+o.axisPaddingLeft+o.axisPaddingRight).attr("y1",self.yZero).attr("y2",self.yZero);zLinePath.transition().duration(o.timing).attr("y1",self.yZero).attr("y2",self.yZero)},_updateScale:function(){var self=this,_unionData=function(){return _.union(self._mainData,self._compData)},scaleData=_unionData(),vis=self._vis,scale,min;delete self.xScale;delete self.yScale;delete self.yZero;if(vis.hasOwnProperty("preUpdateScale")){vis.preUpdateScale(self,scaleData,self._mainData,self._compData)}scaleData=_unionData();scale=_scales.xy(self,scaleData,self._xScaleType,self._yScaleType);self.xScale=scale.x;self.yScale=scale.y;min=self.yScale.domain()[0];self.yZero=min>0?self.yScale(min):self.yScale(0);if(vis.hasOwnProperty("postUpdateScale")){vis.postUpdateScale(self,scaleData,self._mainData,self._compData)}},_enter:function(vis,storage,data,className){var self=this,callbacks={click:self._options.click,mouseover:self._options.mouseover,mouseout:self._options.mouseout};self._checkVisMethod(vis,"enter");vis.enter(self,storage,className,data,callbacks)},_update:function(vis,storage){var self=this;self._checkVisMethod(vis,"update");vis.update(self,storage,self._options.timing)},_exit:function(vis,storage){var self=this;self._checkVisMethod(vis,"exit");vis.exit(self,storage,self._options.timing)},_destroy:function(vis,storage){var self=this;self._checkVisMethod(vis,"destroy");try{vis.destroy(self,storage,self._options.timing)}catch(e){}},_draw:function(){var self=this,o=self._options,comp,compKeys;self._noData=_.flatten(_.pluck(self._mainData,"data").concat(_.pluck(self._compData,"data"))).length===0;self._updateScale();self._drawAxes();self._enter(self._vis,self._mainStorage,self._mainData,".main");self._exit(self._vis,self._mainStorage);self._update(self._vis,self._mainStorage);comp=_.chain(self._compData).groupBy(function(d){return d.type});compKeys=comp.keys();_.each(self._compStorage,function(d,key){if(-1===compKeys.indexOf(key).value()){var vis=_vis[key];self._enter(vis,d,[],".comp."+key.replace(/\W+/g,""));self._exit(vis,d)}});comp.each(function(d,key){var vis=_vis[key],storage;if(!self._compStorage.hasOwnProperty(key)){self._compStorage[key]={}}storage=self._compStorage[key];self._enter(vis,storage,d,".comp."+key.replace(/\W+/g,""));self._exit(vis,storage);self._update(vis,storage)});if(self._noData){o.empty(self,self._selector,self._mainData)}else{o.notempty(self,self._selector)}},_checkVisMethod:function(vis,method){var self=this;if(!vis[method]){throw'Required method "'+method+'" not found on vis type "'+self._type+'".'}}});if(typeof define==="function"&&define.amd&&typeof define.amd==="object"){define(function(){return xChart});return}window.xChart=xChart})(); \ No newline at end of file diff --git a/plugins/web_gui/static/restart.html b/plugins/web_gui/static/restart.html new file mode 100644 index 0000000..57eae96 --- /dev/null +++ b/plugins/web_gui/static/restart.html @@ -0,0 +1,37 @@ + + + + + StarryPy + + + + + + + + + + + + +
    +
    +
    +
    +
    + {% if handler.error_message == "" %} +

    Server has been restarted!

    + {% else %} +

    {{ handler.error_message }}

    + {% end %} +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/plugins/web_gui/web_gui.py b/plugins/web_gui/web_gui.py new file mode 100644 index 0000000..38ef623 --- /dev/null +++ b/plugins/web_gui/web_gui.py @@ -0,0 +1,325 @@ +#:coding=utf-8: +import os +import logging +import json +import tornado.web +import tornado.websocket +import subprocess +from datetime import datetime +from twisted.internet import reactor +from plugins.core.player_manager import UserLevels +from tornado.ioloop import PeriodicCallback + + +class BaseHandler(tornado.web.RequestHandler): + + def get_current_user(self): + return self.get_secure_cookie("player") + + +class LoginHandler(BaseHandler): + + def initialize(self): + self.failed_login = False + + def get(self): + self.render("login.html") + + def post(self): + self.login_user = self.player_manager.get_by_name(self.get_argument("name", strip=False)) + if self.login_user is None: + self.login_user = self.player_manager.get_by_org_name(self.get_argument("name", strip=False)) + + if self.login_user is None or self.get_argument("password") != self.ownerpassword: + self.failed_login = True + self.render("login.html") + else: + self.set_secure_cookie("player", self.get_argument("name", strip=False)) + self.factory.broadcast("An admin has joined the server through Web-GUI.", 0, self.get_argument("name", strip=False)) + self.failed_login = False + self.redirect(self.get_argument("next", "/")) + + +class RestartHandler(BaseHandler): + + def initialize(self): + self.web_gui_user = self.player_manager.get_by_name(self.get_current_user()) + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + if self.web_gui_user.access_level == self.levels["OWNER"]: + self.error_message = "" + self.render("restart.html") + subprocess.call(self.restart_script, shell=True) + else: + self.error_message = "Only owners can restart the server!" + self.render("restart.html") + + +class LogoutHandler(BaseHandler): + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.clear_cookie("player") + self.redirect("/login") + + +class IndexHandler(BaseHandler): + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("index.html") + + +class DashboardHandler(BaseHandler): + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("ajax/dashboard.html") + + +class PlayerListHandler(BaseHandler): + + def initialize(self): + self.playerlist = self.player_manager.all() + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("ajax/playerlist.html") + + +class PlayerOnlineSideBarHandler(BaseHandler): + + def initialize(self): + self.playerlistonline = self.player_manager.who() + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("ajax/playersonline.html") + + +class PlayerOnlineListHandler(BaseHandler): + + def initialize(self): + self.playerlistonline = self.player_manager.who() + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("ajax/playerlistonline.html") + + +class PlayerEditHandler(BaseHandler): + + def initialize(self): + self.web_gui_user = self.player_manager.get_by_name(self.get_current_user()) + self.error_message = "" + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.edit_player = self.player_manager.get_by_name(self.get_argument("playername", strip=False)) + try: + self.error_message = self.get_argument("error_message") + except tornado.web.MissingArgumentError: + self.error_message = "" + self.render("ajax/playeredit.html") + + @tornado.web.authenticated + @tornado.web.asynchronous + def post(self): + self.edit_player = self.player_manager.get_by_name(self.get_argument("old_playername", strip=False)) + if self.web_gui_user.access_level > self.edit_player.access_level: + if self.edit_player.access_level != self.get_argument("access_level"): + self.edit_player.access_level = self.get_argument("access_level") + if self.get_argument("playername", strip=False) != "" and self.edit_player.name != self.get_argument("playername", strip=False): + if self.edit_player.org_name is None: + self.edit_player.org_name = self.edit_player.name + self.edit_player.name = self.get_argument("playername", strip=False) + else: + error_message = "You are not allowed to change this users' data!" + self.redirect("ajax/playeredit.html?playername={n}&error_message={e}".format( + n=self.get_argument("playername", strip=False), e=error_message)) + self.render("ajax/playeredit.html") + + +class PlayerQuickMenuHandler(BaseHandler): + + def initialize(self): + self.edit_player = self.player_manager.get_by_name(self.get_argument("playername", strip=False)) + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("ajax/playerquickmenu.html") + + +class PlayerActionHandler(BaseHandler): + + def initialize(self): + self.web_gui_user = self.player_manager.get_by_name(self.get_current_user()) + self.edit_player = self.player_manager.get_by_name(self.get_argument("info", strip=False)) + + @tornado.web.authenticated + @tornado.web.asynchronous + def post(self): + if self.get_argument("action") == "delete": + if self.web_gui_user.access_level == self.levels["OWNER"]: + if self.edit_player is not None: + self.player_manager.delete(self.edit_player) + response = json.dumps({"status": "OK", "msg": "Player was deleted"}) + else: + response = json.dumps({"status": "ERROR", "msg": "Player not found!"}) + else: + response = json.dumps({"status": "ERROR", "msg": "You don't have permission to do this."}) + elif self.get_argument("action") == "ban": + if self.web_gui_user.access_level >= self.levels["ADMIN"]: + self.player_manager.ban(self.edit_player.ip) + if self.edit_player.logged_in: + protocol = self.factory.protocols[self.edit_player.protocol] + protocol.transport.loseConnection() + response = json.dumps({"status": "OK", "msg": "IP was banned"}) + else: + response = json.dumps({"status": "ERROR", "msg": "You don't have permission to do this."}) + elif self.get_argument("action") == "unban": + if self.web_gui_user.access_level >= self.levels["ADMIN"]: + self.player_manager.unban(self.edit_player.ip) + response = json.dumps({"status": "OK", "msg": "IP was unbanned"}) + else: + response = json.dumps({"status": "ERROR", "msg": "You don't have permission to do this."}) + elif self.get_argument("action") == "kick": + if self.web_gui_user.access_level >= self.levels["ADMIN"]: + if self.edit_player.logged_in: + protocol = self.factory.protocols[self.edit_player.protocol] + protocol.transport.loseConnection() + response = json.dumps({"status": "OK", "msg": "Player was kicked."}) + else: + response = json.dumps({"status": "ERROR", "msg": "Player not online."}) + else: + response = json.dumps({"status": "ERROR", "msg": "You don't have permission to do this."}) + else: + response = json.dumps({"status": "ERROR", "msg": "Invalid action."}) + self.finish(response) + + +class AdminStopHandler(BaseHandler): + + def initialize(self): + self.web_gui_user = self.player_manager.get_by_name(self.get_current_user()) + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + if self.web_gui_user.access_level == self.levels["OWNER"]: + self.error_message = "" + self.render("adminstop.html") + reactor.stop() + else: + self.error_message = "Only owners can stop the server!" + self.render("adminstop.html") + + +class WebSocketChatHandler(tornado.websocket.WebSocketHandler): + + def initialize(self): + self.clients = [] + self.callback = PeriodicCallback(self.update_chat, 500) + self.web_gui_user = self.player_manager.get_by_name(self.get_secure_cookie("player")) + + def open(self, *args): + self.clients.append(self) + for msg in self.messages_log: + self.write_message(msg) + self.callback.start() + + def on_message(self, message): + messagejson = json.loads(message) + + self.messages.append(message) + self.messages_log.append(message) + self.factory.broadcast("^yellow;<{d}> <^red;{u}^yellow;> {m}".format( + d=datetime.now().strftime("%H:%M"), u=self.web_gui_user.name, m=messagejson["message"]), 0, "") + + def update_chat(self): + if len(self.messages) > 0: + for message in sorted(self.messages): + for client in self.clients: + client.write_message(message) + del self.messages[0:len(self.messages)] + + def on_close(self): + self.clients.remove(self) + self.callback.stop() + + +class WebChatJsHandler(BaseHandler): + + @tornado.web.authenticated + @tornado.web.asynchronous + def get(self): + self.render("js/webgui.chat.js") + + +class WebGuiApp(tornado.web.Application): + def __init__(self, port, ownerpassword, playermanager, factory, cookie_secret, messages, messages_log, + restart_script): + logging.getLogger('tornado.general').addHandler(logging.FileHandler(self.config["log_path"])) + logging.getLogger('tornado.application').addHandler(logging.FileHandler(self.config["log_path"])) + logging.getLogger('tornado.access').addHandler(logging.FileHandler(self.config["log_path_access"])) + + BaseHandler.factory = factory + BaseHandler.player_manager = playermanager + BaseHandler.messages = messages + BaseHandler.messages_log = messages_log + BaseHandler.restart_script = restart_script + BaseHandler.ownerpassword = ownerpassword + BaseHandler.levels = UserLevels.ranks + WebChatJsHandler.wsport = port + WebSocketChatHandler.factory = factory + WebSocketChatHandler.player_manager = playermanager + WebSocketChatHandler.messages = messages + WebSocketChatHandler.messages_log = messages_log + + handlers = [ + (r"/login", LoginHandler), + (r"/logout", LogoutHandler), + (r"/restart", RestartHandler), + (r'/chat', WebSocketChatHandler), + (r'/stopserver', AdminStopHandler), + (r'/ajax/playerlistonline.html', PlayerOnlineListHandler), + (r'/ajax/playerlist.html', PlayerListHandler), + (r'/ajax/playeredit.html', PlayerEditHandler), + (r'/ajax/playerquickmenu.html', PlayerQuickMenuHandler), + (r'/ajax/playersonline.html', PlayerOnlineSideBarHandler), + (r'/ajax/dashboard.html', DashboardHandler), + (r'/ajax/playeraction', PlayerActionHandler), + (r'/js/webgui.chat.js', WebChatJsHandler), + (r'/index.html', IndexHandler), + (r'/', IndexHandler), + (r'/ajax/(.*)', tornado.web.StaticFileHandler, + {'path': os.path.join(os.path.dirname(__file__), 'static/ajax')}), + (r'/css/(.*)', tornado.web.StaticFileHandler, + {'path': os.path.join(os.path.dirname(__file__), 'static/css')}), + (r'/js/(.*)', tornado.web.StaticFileHandler, + {'path': os.path.join(os.path.dirname(__file__), 'static/js')}), + (r'/plugins/(.*)', tornado.web.StaticFileHandler, + {'path': os.path.join(os.path.dirname(__file__), 'static/plugins')}), + (r'/img/(.*)', tornado.web.StaticFileHandler, + {'path': os.path.join(os.path.dirname(__file__), 'static/img')}), + (r'/images/(.*)', tornado.web.StaticFileHandler, + {'path': os.path.join(os.path.dirname(__file__), 'static/images')}) + ] + settings = dict( + template_path=os.path.join(os.path.dirname(__file__), "static"), + login_url="/login", + cookie_secret=cookie_secret, + xsrf_cookies=True, + debug=True + ) + tornado.web.Application.__init__(self, handlers, **settings) + self.listen(port) \ No newline at end of file diff --git a/plugins/web_gui/web_gui_plugin.py b/plugins/web_gui/web_gui_plugin.py new file mode 100644 index 0000000..b3c642f --- /dev/null +++ b/plugins/web_gui/web_gui_plugin.py @@ -0,0 +1,88 @@ +#:coding=utf-8: +import os +import string +import random +import json +from datetime import datetime +from base_plugin import BasePlugin +from plugins.core.player_manager import PlayerManager +from packets import chat_sent, client_connect +from . import web_gui +import tornado.ioloop +from tornado.platform.twisted import TwistedIOLoop +TwistedIOLoop().install() + + +class WebGuiPlugin(BasePlugin, PlayerManager): + name = "web_gui" + depends = ['player_manager'] + + def __init__(self): + super(WebGuiPlugin, self).__init__() + try: + self.port = int(self.config.plugin_config['port']) + except (AttributeError, ValueError): + self.port = 8083 + self.ownerpassword = self.config.plugin_config['ownerpassword'] + self.restart_script = self.config.plugin_config['restart_script'] + if self.config.plugin_config['cookie_token'] == "" or not self.config.plugin_config['remember_cookie_token']: + self.cookie_token = self.config.plugin_config['cookie_token'] = self.generate_cookie_token() + else: + self.cookie_token = self.config.plugin_config['cookie_token'] + self.messages = [] + self.messages_log = [] + + def activate(self): + super(WebGuiPlugin, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + web_gui.WebGuiApp.config = self.config.plugin_config + self.web_gui_app = web_gui.WebGuiApp(port=self.port, ownerpassword=self.ownerpassword, + playermanager=self.player_manager, factory=self.factory, + cookie_secret=self.cookie_token, messages=self.messages, + messages_log=self.messages_log, restart_script=self.restart_script) + self.logger.info("WebGUI listening on port {p}".format(p=self.port)) + self.gui_instance = tornado.ioloop.IOLoop.instance() + + def deactivate(self): + super(WebGuiPlugin, self).deactivate() + self.gui_instance.stop() + + def generate_cookie_token(self): + chars = string.ascii_letters + string.digits + random.seed(os.urandom(1024)) + return "".join(random.choice(chars) for i in range(64)) + + def on_chat_sent(self, data): + parsed = chat_sent().parse(data.data) + msgdate = datetime.now().strftime("[%H:%M:%S]") + message = json.dumps({"msgdate": msgdate, "author": self.protocol.player.name, + "message": parsed.message.decode("utf-8")}) + self.messages.append(message) + self.messages_log.append(message) + + return True + + def on_client_connect(self, data): + parsed = client_connect().parse(data.data) + msgdate = datetime.now().strftime("[%H:%M:%S]") + connect_player = self.player_manager.get_by_org_name(parsed.name.decode("utf-8")) + try: + if self.player_manager.check_bans(connect_player.ip): + msgtxt = "Banned Player {p} tried to join the server.".format(p=connect_player.name) + else: + msgtxt = "Player {p} has joined the server.".format(p=connect_player.name) + except AttributeError: + msgtxt = "New player has joined the server." + message = json.dumps({"msgdate": msgdate, "author": "SERVER", "message": msgtxt}) + self.messages.append(message) + self.messages_log.append(message) + + return True + + def on_client_disconnect(self, data): + if self.protocol.player is not None: + msgdate = datetime.now().strftime("[%H:%M:%S]") + msgtxt = "Player {p} has left the server.".format(p=self.protocol.player.name.encode("utf-8")) + message = json.dumps({"msgdate": msgdate, "author": "SERVER", "message": msgtxt}) + self.messages.append(message) + self.messages_log.append(message) From 210a4f7e148a6f4fee12043e1efb5208a03e481f Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Thu, 5 Feb 2015 04:02:23 -0500 Subject: [PATCH 82/95] People were skipping the wrapper by changing their character name with starcheat. The current solution to this matter, is that if a changed-named player connects, it uses their original name, and possibly adds a _ to the end as well. Each time they reconnect to the same-running server session, another _ will be added to the end of the name. While not ideal, this is better than skipping the wrapper. --- plugins/core/player_manager/manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index d51d7e2..ec984e5 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -251,7 +251,6 @@ def fetch_or_create(self, uuid, name, org_name, ip, protocol=None): if player.name != name: logger.info("Detected username change.") player.name = name - self.protocol.player.name = name if ip not in player.ips: player.ips.append(IPAddress(ip=ip)) player.ip = ip From 10859273aab1d59435f75d1af71d45c9bddea2e1 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Thu, 5 Feb 2015 04:10:19 -0500 Subject: [PATCH 83/95] Starter items got skipped for some reason. Fixing. --- plugins/starteritems/__init__.py | 1 + plugins/starteritems/starteritems_plugin.py | 40 +++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 plugins/starteritems/__init__.py create mode 100644 plugins/starteritems/starteritems_plugin.py diff --git a/plugins/starteritems/__init__.py b/plugins/starteritems/__init__.py new file mode 100644 index 0000000..b77a5e8 --- /dev/null +++ b/plugins/starteritems/__init__.py @@ -0,0 +1 @@ +from starteritems_plugin import StarterItems \ No newline at end of file diff --git a/plugins/starteritems/starteritems_plugin.py b/plugins/starteritems/starteritems_plugin.py new file mode 100644 index 0000000..a89647e --- /dev/null +++ b/plugins/starteritems/starteritems_plugin.py @@ -0,0 +1,40 @@ +from base_plugin import SimpleCommandPlugin +from utility_functions import give_item_to_player +from plugins.core.player_manager import permissions, UserLevels + + +class StarterItems(SimpleCommandPlugin): + """ + Welcomes new players by giving them a bunch of items. + """ + name = "starteritems_plugin" + depends = ["command_dispatcher", "player_manager"] + commands = ["starteritems"] + auto_activate = True + + def activate(self): + super(StarterItems, self).activate() + self.player_manager = self.plugins['player_manager'].player_manager + + @permissions(UserLevels.GUEST) + def starteritems(self, data): + """Gives you some starter items (only once).\nSyntax: /starteritems""" + try: + my_storage = self.protocol.player.storage + except AttributeError: + return + if not 'given_starter_items' in my_storage or my_storage['given_starter_items'] == "False": + my_storage['given_starter_items'] = "True" + self.give_items() + self.send_greetings() + self.logger.info("Gave starter items to %s.", self.protocol.player.name) + self.protocol.player.storage = my_storage + else: + self.protocol.send_chat_message("^red;You have already received a starter pack :O") + + def give_items(self): + for item in self.config.plugin_config["items"]: + give_item_to_player(self.protocol, item[0], item[1]) + + def send_greetings(self): + self.protocol.send_chat_message(self.config.plugin_config["message"]) From b25b52aada747282fdf60871f19f5e848355f5c8 Mon Sep 17 00:00:00 2001 From: kharidiron Date: Fri, 6 Feb 2015 11:31:11 -0800 Subject: [PATCH 84/95] added tornado Needed for the web_gui. --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 33ecf33..f156fe6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ sqlalchemy twisted enum34 construct -nose \ No newline at end of file +tornado +nose From d6d96b849967d18f5e7a0178968484bfe58ebf90 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 06:12:34 -0500 Subject: [PATCH 85/95] Some packet updating and cleanup. --- packets/data_types.py | 2 + packets/packet_types.py | 169 ++++++++++++++++++++++++---------------- 2 files changed, 102 insertions(+), 69 deletions(-) diff --git a/packets/data_types.py b/packets/data_types.py index 6570456..0d819c4 100644 --- a/packets/data_types.py +++ b/packets/data_types.py @@ -108,6 +108,8 @@ def _parse(self, stream, context): elif x == 3: flag = Flag("").parse_stream(stream) return Field("", 16).parse_stream(stream).encode("hex") + elif x == 4: + return star_string().parse_stream(stream) def _build(self, obj, stream, context): if len(obj) == 32: _write_stream(stream, 1, chr(3)) diff --git a/packets/packet_types.py b/packets/packet_types.py index 67f7097..ff7fac4 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -91,16 +91,7 @@ def _encode(self, obj, context): def _decode(self, obj, context): return obj.encode("hex") - -# may need to be corrected. new version only has hash, uses ByteArray -handshake_response = lambda name="handshake_response": Struct(name, - star_string("claim_response"), - star_string("hash")) - -# small correction. added proper context. may need to check if this is correct (need double. used bfloat64). -universe_time_update = lambda name="universe_time": Struct(name, - #VLQ("unknown")) - BFloat64("universe_time")) +# ---------- Utility constructs --------- packet = lambda name="base_packet": Struct(name, Byte("id"), @@ -112,27 +103,86 @@ def _decode(self, obj, context): Byte("id"), SignedVLQ("payload_size")) +connection = lambda name="connection": Struct(name, + GreedyRange(Byte("compressed_data"))) + +celestial_coordinate = lambda name="celestial_coordinate": Struct(name, + SBInt32("x"), + SBInt32("y"), + SBInt32("z"), + SBInt32("planet"), + SBInt32("satellite")) + +projectile = DictVariant("projectile") + +# --------------------------------------- + +# ----- Primary connection sequence ----- + +# (0) - ProtocolVersion : S -> C protocol_version = lambda name="protocol_version": Struct(name, UBInt32("server_build")) -connection = lambda name="connection": Struct(name, - GreedyRange(Byte("compressed_data"))) +# (7) - ClientConnect : C -> S +client_connect = lambda name="client_connect": Struct(name, + VLQ("asset_digest_length"), + String("asset_digest", + lambda ctx: ctx.asset_digest_length), + Flag("uuid_exists"), + If(lambda ctx: ctx.uuid_exists is True, + HexAdapter(Field("uuid", 16)) + ), + star_string("name"), + star_string("species"), + StarByteArray("ship_data"), + UBInt32("ship_level"), + UBInt32("max_fuel"), + VLQ("capabilities_length"), + Array(lambda ctx: ctx.capabilities_length, + Struct("capabilities", + star_string("value"))), + star_string("account")) -# may need to be corrected. new version only has salt, uses ByteArray +# (3) - HandshakeChallenge : S -> C handshake_challenge = lambda name="handshake_challenge": Struct(name, - star_string("claim_message"), - star_string("salt"), - SBInt32("round_count")) + StarByteArray("salt")) + +# (9) - HandshakeResponse : C -> S +handshake_response = lambda name="handshake_response": Struct(name, + star_string("hash")) -# Needs to be corrected to include 'celestial information' as well as proper reject -# sucess handling. +# (2) - ConnectResponse : S -> C connect_response = lambda name="connect_response": Struct(name, Flag("success"), VLQ("client_id"), star_string("reject_reason"), - GreedyRange(star_string("celestial_info"))) + Flag("celestial_info_exists"), + If(lambda ctx: ctx.celestial_info_exists, + Struct( + "celestial_data", + SBInt32("planet_orbital_levels"), + SBInt32("satellite_orbital_levels"), + SBInt32("chunk_size"), + SBInt32("xy_min"), + SBInt32("xy_max"), + SBInt32("z_min"), + SBInt32("z_max")))) + +# --------------------------------------- + +# (1) - ServerDisconnect +server_disconnect = lambda name="server_disconnect": Struct(name, + star_string("reason")) + +# (5) - UniverseTimeUpdate +universe_time_update = lambda name="universe_time": Struct(name, + BFloat64("universe_time")) + +# (8) - ClientDisconnectRequest +client_disconnect_request = lambda name="client_disconnect_request": Struct(name, + Byte("data")) -# corrected. needs testing +# (4) - ChatReceived chat_received = lambda name="chat_received": Struct(name, Enum(Byte("mode"), CHANNEL=0, @@ -144,7 +194,7 @@ def _decode(self, obj, context): star_string("name"), star_string("message")) -# corrected. shouldn't need too much testing +# (12) - ChatSent chat_sent = lambda name="chat_sent": Struct(name, star_string("message"), Enum(Byte("send_mode"), @@ -158,39 +208,7 @@ def _decode(self, obj, context): message=message, send_mode=send_mode)) -# quite a bit of guesswork and hackery here with the ship_upgrades. -client_connect = lambda name="client_connect": Struct(name, - VLQ("asset_digest_length"), - String("asset_digest", - lambda ctx: ctx.asset_digest_length), - Flag("uuid_exists"), - If(lambda ctx: ctx.uuid_exists is True, - HexAdapter(Field("uuid", 16)) - ), - star_string("name"), - star_string("species"), - StarByteArray("ship_data"), - UBInt32("ship_level"), - UBInt32("max_fuel"), - VLQ("capabilities"), - star_string("account")) - -server_disconnect = lambda name="server_disconnect": Struct(name, - star_string("reason")) - -client_disconnect_request = lambda name="client_disconnect_request": Struct(name, - Byte("data")) - -celestial_request = lambda name="celestial_request": Struct(name, - GreedyRange(star_string("requests"))) - -celestial_coordinate = lambda name="celestial_coordinate": Struct(name, - SBInt32("x"), - SBInt32("y"), - SBInt32("z"), - SBInt32("planet"), - SBInt32("satellite")) - +# (10) - PlayerWarp player_warp = lambda name="player_warp": Struct(name, Enum(UBInt8("warp_type"), WARP_TO=0, @@ -205,6 +223,7 @@ def _decode(self, obj, context): warp_type=t, world_id=world_id)) +# (11) - FlyShip fly_ship = lambda name="fly_ship": Struct(name, celestial_coordinate()) @@ -217,22 +236,39 @@ def _decode(self, obj, context): planet=planet, satellite=satellite))) -# partially correct. Needs work on dungeon ID value +# (13) - CelestialRequest +celestial_request = lambda name="celestial_request": Struct(name, + GreedyRange(star_string("requests"))) + +# (14) - ClientContextUpdate +client_context_update = lambda name="client_context": Struct(name, + VLQ("length"), + Byte("arguments"), + Array(lambda ctx: ctx.arguments, + Struct("key", + Variant("value")))) + +# (15) - WorldStart world_start = lambda name="world_start": Struct(name, - Variant("planet"), # rename to templateData? + Variant("planet"), StarByteArray("sky_data"), StarByteArray("weather_data"), - #dungeon id stuff here + # Dungeon ID stuff here BFloat32("x"), BFloat32("y"), Variant("world_properties"), UBInt32("client_id"), Flag("local_interpolation")) +# (16) - WorldStop world_stop = lambda name="world_stop": Struct(name, star_string("status")) -# I THINK this is ok. Will test later. +# (17) - CentralStructureUpdate +central_structure_update = lambda name="central_structure_update": Struct(name, + Variant("structureData")) + +# (23) - GiveItem give_item = lambda name="give_item": Struct(name, star_string("name"), VLQ("count"), @@ -246,6 +282,7 @@ def _decode(self, obj, context): variant_type=7, description='')) +# (52) - UpdateWorldProperties update_world_properties = lambda name="world_properties": Struct(name, UBInt8("count"), Array(lambda ctx: ctx.count, @@ -258,6 +295,7 @@ def _decode(self, obj, context): count=len(dictionary), properties=[Container(key=k, value=Container(type="SVLQ", data=v)) for k, v in dictionary.items()])) +# (45) - EntityCreate entity_create = Struct("entity_create", GreedyRange( Struct("entity", @@ -266,18 +304,11 @@ def _decode(self, obj, context): String("entity", lambda ctx: ctx.entity_size), SignedVLQ("entity_id")))) +# (46) - EntityUpdate entity_update = lambda name="entity_update": Struct(name, UBInt32("entity_id"), StarByteArray("delta")) -client_context_update = lambda name="client_context": Struct(name, - VLQ("length"), - Byte("arguments"), - Array(lambda ctx: ctx.arguments, - Struct("key", - Variant("value")))) - -central_structure_update = lambda name="central_structure_update": Struct(name, - Variant("structureData")) - -projectile = DictVariant("projectile") +# (53) - Heartbeat +heartbeat = lambda name="heartbeat": Structure(name, + UBInt64("remote_step")) From 13aa707af292a643734c909bbaa992b592ee6599 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 06:15:39 -0500 Subject: [PATCH 86/95] Setup a shared-secret auth system for mod+ users to prevent user spoofing issues. May need more testing and code cleanup. --- config/config.json.default | 1 + plugins/core/player_manager/manager.py | 14 ++++++++++++-- plugins/core/player_manager/plugin.py | 12 +++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 90b2d88..cef21ff 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -1,4 +1,5 @@ { + "admin_ss": "tester", "bind_address": "", "bind_port": 21025, "chat_prefix": "#", diff --git a/plugins/core/player_manager/manager.py b/plugins/core/player_manager/manager.py index ec984e5..7460472 100644 --- a/plugins/core/player_manager/manager.py +++ b/plugins/core/player_manager/manager.py @@ -148,6 +148,7 @@ class Player(Base): last_seen = Column(DateTime) access_level = Column(Integer) logged_in = Column(Boolean) + admin_logged_in = Column(Boolean) protocol = Column(String) client_id = Column(Integer) ip = Column(String) @@ -215,6 +216,7 @@ def __init__(self, config): with _autoclosing_session(self.sessionmaker) as session: for player in session.query(Player).filter_by(logged_in=True).all(): player.logged_in = False + player.admin_logged_in = False player.protocol = None session.commit() @@ -233,7 +235,7 @@ def _cache_and_return_from_session(self, session, record, collection=False): return to_return - def fetch_or_create(self, uuid, name, org_name, ip, protocol=None): + def fetch_or_create(self, uuid, name, org_name, admin_logged_in, ip, protocol=None): with _autoclosing_session(self.sessionmaker) as session: if session.query(Player).filter_by(uuid=uuid, logged_in=True).first(): raise AlreadyLoggedIn @@ -256,12 +258,14 @@ def fetch_or_create(self, uuid, name, org_name, ip, protocol=None): player.ip = ip player.protocol = protocol player.last_seen = datetime.datetime.now() + player.admin_logged_in = admin_logged_in else: logger.info("Adding new player with name: %s" % name) player = Player(uuid=uuid, name=name, org_name=org_name, last_seen=datetime.datetime.now(), access_level=int(UserLevels.GUEST), logged_in=False, + admin_logged_in=False, protocol=protocol, client_id=-1, ip=ip, @@ -385,7 +389,13 @@ def wrapper(f): @wraps(f) def wrapped_function(self, *args, **kwargs): if self.protocol.player.access_level >= level: - return f(self, *args, **kwargs) + if level >= UserLevels.MODERATOR: + if self.protocol.player.admin_logged_in == 0: + self.protocol.send_chat_message("^red;You're not logged in, so I can't let you do that.^yellow;") + else: + return f(self, *args, **kwargs) + else: + return f(self, *args, **kwargs) else: self.protocol.send_chat_message("You are not authorized to do this.") return False diff --git a/plugins/core/player_manager/plugin.py b/plugins/core/player_manager/plugin.py index 62e4ca1..1762374 100644 --- a/plugins/core/player_manager/plugin.py +++ b/plugins/core/player_manager/plugin.py @@ -22,6 +22,7 @@ def activate(self): self.l_call = LoopingCall(self.check_logged_in) self.l_call.start(1, now=False) self.regexes = self.config.plugin_config['name_removal_regexes'] + self.adminss = self.config.plugin_config['admin_ss'] def deactivate(self): del self.player_manager @@ -30,6 +31,7 @@ def check_logged_in(self): for player in self.player_manager.who(): if player.protocol not in self.factory.protocols.keys(): player.logged_in = False + player.admin_logged_in = False def on_client_connect(self, data): client_data = client_connect().parse(data.data) @@ -59,11 +61,17 @@ def on_client_connect(self, data): #original_name += rnd_append #client_data.name += rnd_append + if client_data.account == self.adminss: + admin_login = True + else: + admin_login = False + original_name = client_data.name client_data.name = changed_name self.protocol.player = self.player_manager.fetch_or_create( name=client_data.name, org_name=original_name, + admin_logged_in = admin_login, uuid=str(client_data.uuid), ip=self.protocol.transport.getPeer().host, protocol=self.protocol.id, @@ -115,10 +123,7 @@ def on_connect_response(self, data): return True def after_world_start(self, data): - # may need to add more world types in here world_start = packets.world_start().parse(data.data) - # self.logger.debug("World start: %s", world_start) # debug world packets - # self.logger.debug("World start raw: %s", data.data.encode('hex')) # debug world packets if 'ship.maxFuel' in world_start['world_properties']: self.logger.info("Player %s is now on a ship.", self.protocol.player.name) self.protocol.player.on_ship = True @@ -139,6 +144,7 @@ def on_client_disconnect_request(self, player): if self.protocol.player is not None and self.protocol.player.logged_in: self.logger.info("Player disconnected: %s", self.protocol.player.name) self.protocol.player.logged_in = False + self.protocol.player.admin_logged_in = False return True @permissions(UserLevels.REGISTERED) From 336972110f48eab57f6c6a0909294495790713f6 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 06:34:37 -0500 Subject: [PATCH 87/95] oops, forgot to fix the config.json file. --- config/config.json.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json.default b/config/config.json.default index cef21ff..2fc90b4 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -1,5 +1,4 @@ { - "admin_ss": "tester", "bind_address": "", "bind_port": 21025, "chat_prefix": "#", @@ -197,6 +196,7 @@ "auto_activate": true }, "player_manager": { + "admin_ss": "tester", "auto_activate": true, "name_removal_regexes": [ "\\^#[\\w]+;", From d743169f83c7a96445ddb91f14b41c83ec63ca08 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 16:52:12 -0500 Subject: [PATCH 88/95] Cleanup after changing my vim flow --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8697f98..65a156f 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ nosetests.xml # Vim mess cleanup *.swp +*.un~ From 1296719f28cec24a86983a1f01e78f55b8f42506 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 16:53:01 -0500 Subject: [PATCH 89/95] More cleanup for vim --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 65a156f..5032ac7 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ nosetests.xml # Vim mess cleanup *.swp *.un~ +.ropeproject/ From d90d15427910e66437d66dfad8d409acf8df9e6e Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 17:14:48 -0500 Subject: [PATCH 90/95] Change logging to use rotating log files, kept for 5 days, rotated at midnight. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5032ac7..a7e4d21 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ nosetests.xml *.db *.db-journal *.log +*.log.* .idea/ # Vim mess cleanup From 24807b79a475337823cd41444599a9f5172e5265 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Sat, 7 Feb 2015 17:15:17 -0500 Subject: [PATCH 91/95] helps if I add the file... --- server.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server.py b/server.py index 11a23ee..87b466f 100644 --- a/server.py +++ b/server.py @@ -3,6 +3,7 @@ #import gettext import locale import logging +import logging.handlers from uuid import uuid4 import sys import socket @@ -24,11 +25,11 @@ VERSION = "1.4.4" -VDEBUG_LVL = 9 +VDEBUG_LVL = 9 logging.addLevelName(VDEBUG_LVL, "VDEBUG") def vdebug(self, message, *args, **kws): if self.isEnabledFor(VDEBUG_LVL): - self._log(VDEBUG_LVL, message, args, **kws) + self._log(VDEBUG_LVL, message, args, **kws) logging.Logger.vdebug = vdebug def port_check(upstream_hostname, upstream_port): @@ -715,7 +716,7 @@ def init_localization(): log_level = "VDEBUG" else: log_level = logging.INFO - + print('Setup console logging...') console_handle = logging.StreamHandler(sys.stdout) console_handle.setLevel(log_level) @@ -723,7 +724,7 @@ def init_localization(): console_handle.setFormatter(log_format) print('Setup file-based logging...') - logfile_handle = logging.FileHandler("server.log") + logfile_handle = logging.handlers.TimedRotatingFileHandler("server.log", when='midnight', interval=5, backupCount=4) logfile_handle.setLevel(log_level) logger.addHandler(logfile_handle) logfile_handle.setFormatter(log_format) From 269a2c39307d43a2e2e7f5fdcbb9e68a45fc4867 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 10 Feb 2015 23:28:17 -0500 Subject: [PATCH 92/95] Added more packet types... used some of these to fix the issues with planet_protect. --- base_plugin.py | 6 + packets/packet_types.py | 118 +++++++++++++++--- .../planet_protect/planet_protect_plugin.py | 38 ++++-- plugins/warpy_plugin/warpy_plugin.py | 6 - server.py | 13 +- 5 files changed, 150 insertions(+), 31 deletions(-) diff --git a/base_plugin.py b/base_plugin.py index 4cbd2bf..d5ac26a 100644 --- a/base_plugin.py +++ b/base_plugin.py @@ -161,6 +161,9 @@ def on_entity_update(self, data): def on_entity_destroy(self, data): return True + def on_hit_request(self, data): + return True + def on_status_effect_request(self, data): return True @@ -311,6 +314,9 @@ def after_entity_update(self, data): def after_entity_destroy(self, data): return True + def after_hit_request(self, data): + return True + def after_status_effect_request(self, data): return True diff --git a/packets/packet_types.py b/packets/packet_types.py index ff7fac4..88ee24c 100644 --- a/packets/packet_types.py +++ b/packets/packet_types.py @@ -79,6 +79,22 @@ class EntityType(IntEnum): NPC = 8 +class InteractionType(IntEnum): + NONE = 0 + OPEN_COCKPIT_INTERFACE = 1 + OPEN_CONTAINER = 2 + SIT_DOWN = 3 + OPEN_CRAFTING_INTERFACE = 4 + PLAY_CINEMATIC = 5 + OPEN_SONGBOOK_INTERFACE = 6 + OPEN_NPC_CRAFTING_INTERFACE = 7 + OPEN_NPC_BOUNTY_INTERFACE = 8 + OPEN_AI_INTERFACE = 9 + OPEN_TELEPORT_DIALOG = 10 + SHOW_POPUP = 11 + SCRIPT_CONSOLE = 12 + + class PacketOutOfOrder(Exception): pass @@ -282,6 +298,94 @@ def _decode(self, obj, context): variant_type=7, description='')) +# (38) - SwapInContainer +swap_in_container = lambda name="swap_in_container": Struct(name, + VLQ("entity_id"), # Where are we putting stuff + star_string("item_name"), + VLQ("count"), + Byte("variant_type"), + StarByteArray("item_description"), + VLQ("slot")) + +# (24) - SwapInContainerResult - aka what item is selected / in our hand (does +# not mean wielding) +swap_in_container_result = lambda name="swap_in_container_result": Struct(name, + star_string("item_name"), + VLQ("count"), + Byte("variant_type"), + GreedyRange(StarByteArray("item_description"))) + +# (34) - SpawnEntity +spawn_entity = lambda name="spawn_entity": Struct(name, + GreedyRange( + Struct("entity", + Byte("entity_type"), + VLQ("payload_size"), + String("payload", lambda ctx: ctx.payload_size)))) + +# (45) - EntityCreate +entity_create = lambda name="entity_create": Struct(name, + GreedyRange( + Struct("entity", + Byte("entity_type"), + VLQ("payload_size"), + String("payload", lambda ctx: ctx.payload_size), + VLQ("entity_id")))) + +# (46) - EntityUpdate +entity_update = lambda name="entity_update": Struct(name, + UBInt32("entity_id"), + StarByteArray("delta")) + +# (47) - EntityDestroy +entity_destroy = lambda name="entity_destroy": Struct(name, + UBInt32("entity_id"), + Flag("death")) + +# (30) - EntityInteract +entity_interact = lambda name="entity_interact": Struct(name, + UBInt32("source_entity_id"), + BFloat32("source_x"), + BFloat32("source_y"), + UBInt32("target_entity_id")) + +# (26) - EntityInteractResult +entity_interact_result = lambda name="entity_interact_result": Struct(name, + UBInt32("interaction_type"), + UBInt32("target_entity_id"), + Variant("entity_data")) + +# (48) - HitRequest +hit_request = lambda name="hit_request": Struct(name, + UBInt32("source_entity_id"), + UBInt32("target_entity_id")) + +# (DamageRequest) - DamageRequest +damage_request = lambda name="damage_request": Struct(name, + UBInt32("source_entity_id"), + UBInt32("target_entity_id"), + UBint8("hit_type"), + UBInt8("damage_type"), + BFloat32("damage"), + BFloat32("knockback_x"), + BFloat32("knockback_y"), + UBInt32("source_entity_id_wut"), + star_string("damage_source_kind"), + GreedyReange(star_string("stuats_effects")) + ) + +# (50) - DamageNotification +damage_notification = lambda name="damage_notification": Struct(name, + UBInt32("source_entity_id"), + UBInt32("source_entity_id_wut"), + UBInt32("target_entity_id"), + VLQ("x"), + VLQ("y"), + VLQ("damage"), + star_string("damage_kind"), + star_string("target_material"), + Flag("killed")) + # (52) - UpdateWorldProperties update_world_properties = lambda name="world_properties": Struct(name, UBInt8("count"), @@ -295,20 +399,6 @@ def _decode(self, obj, context): count=len(dictionary), properties=[Container(key=k, value=Container(type="SVLQ", data=v)) for k, v in dictionary.items()])) -# (45) - EntityCreate -entity_create = Struct("entity_create", - GreedyRange( - Struct("entity", - Byte("entity_type"), - VLQ("entity_size"), - String("entity", lambda ctx: ctx.entity_size), - SignedVLQ("entity_id")))) - -# (46) - EntityUpdate -entity_update = lambda name="entity_update": Struct(name, - UBInt32("entity_id"), - StarByteArray("delta")) - # (53) - Heartbeat heartbeat = lambda name="heartbeat": Structure(name, UBInt64("remote_step")) diff --git a/plugins/planet_protect/planet_protect_plugin.py b/plugins/planet_protect/planet_protect_plugin.py index 1d4548f..1ae345d 100644 --- a/plugins/planet_protect/planet_protect_plugin.py +++ b/plugins/planet_protect/planet_protect_plugin.py @@ -1,7 +1,7 @@ import re from base_plugin import SimpleCommandPlugin from plugins.core.player_manager import UserLevels, permissions -from packets import entity_create, EntityType, star_string +from packets import entity_create, EntityType, star_string, entity_interact_result, InteractionType from utility_functions import extract_name @@ -168,13 +168,37 @@ def on_entity_create(self, data): if name in self.player_planets[self.protocol.player.planet]: return True else: - entities = entity_create.parse(data.data) + entities = entity_create().parse(data.data) for entity in entities.entity: + self.logger.vdebug("Entity Type: %s", entity.entity_type) if entity.entity_type == EntityType.PROJECTILE: - if self.block_all: return False - p_type = star_string("").parse(entity.entity) + self.logger.vdebug("projectile detected") + if self.block_all: + return False + p_type = star_string("").parse(entity.payload) + self.logger.vdebug("projectile: %s", p_type) if p_type in self.blacklist: - self.logger.info( - "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", - self.protocol.player.org_name, p_type) + self.logger.vdebug("%s",self.blacklist) + if p_type in ['water']: + self.logger.vdebug( + "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", + self.protocol.player.org_name, p_type) + else: + self.logger.info( + "Player %s attempted to use a prohibited projectile, %s, on a protected planet.", + self.protocol.player.org_name, p_type) return False + + def on_entity_interact_result(self, data): + """Chest protection""" + if self.protocol.player.planet in self.protected_planets and self.protocol.player.access_level < UserLevels.ADMIN: + self.logger.vdebug("User %s attmepted to interact on a protected planet.", self.protocol.player.name) + name = self.protocol.player.org_name + if name in self.player_planets[self.protocol.player.planet]: + return True + else: + entity = entity_interact_result().parse(data.data) + if entity.interaction_type == InteractionType.OPEN_CONTAINER: + self.logger.vdebug("User %s attmepted to open container ID %s", self.protocol.player.name, entity.target_entity_id) + self.logger.vdebug("This is not permitted.") + return False diff --git a/plugins/warpy_plugin/warpy_plugin.py b/plugins/warpy_plugin/warpy_plugin.py index 8268638..971d4c2 100644 --- a/plugins/warpy_plugin/warpy_plugin.py +++ b/plugins/warpy_plugin/warpy_plugin.py @@ -18,12 +18,6 @@ def activate(self): super(Warpy, self).activate() self.player_manager = self.plugins['player_manager'].player_manager - ## Warp debugging - #def on_player_warp(self, data): - # self.logger.debug("Warp packet: %s", data.data.encode('hex')) - # warp_data = player_warp().parse(data.data) - # self.logger.debug("Warp packet: %s", warp_data) - @permissions(UserLevels.MODERATOR) def warp(self, name): """Warps you to a player's ship (or player to player).\nSyntax: /warp [player] (to player)""" diff --git a/server.py b/server.py index 87b466f..d447132 100644 --- a/server.py +++ b/server.py @@ -115,7 +115,7 @@ def __init__(self): packets.Packets.ENTITY_CREATE: self.entity_create, # 45 packets.Packets.ENTITY_UPDATE: self.entity_update, # 46 packets.Packets.ENTITY_DESTROY: self.entity_destroy, # 47 - packets.Packets.HIT_REQUEST: lambda x: True, # 48 + packets.Packets.HIT_REQUEST: self.hit_request, # 48 packets.Packets.DAMAGE_REQUEST: lambda x: True, # 49 packets.Packets.DAMAGE_NOTIFICATION: self.damage_notification, # 50 packets.Packets.CALL_SCRIPTED_ENTITY: lambda x: True, # 51 @@ -152,8 +152,8 @@ def string_received(self, packet): """ if 53 >= packet.id: # DEBUG - print all packet IDs going to client - #if packet.id not in [14, 44, 46, 53]: - # logger.info("From Client: %s", packet.id) + if packet.id not in [14, 44, 45, 46, 47, 51, 53]: + logger.info("From Client: %s", packet.id) if self.handle_starbound_packets(packet): self.client_protocol.transport.write( packet.original_data) @@ -342,6 +342,10 @@ def entity_update(self, data): def entity_destroy(self, data): return True + @route + def hit_request(self, data): + return True + @route def status_effect_request(self, data): return True @@ -543,7 +547,8 @@ def string_received(self, packet): """ try: # DEBUG - print all packet IDs coming from client - # logger.info("From Server: %s", packet.id) + if packet.id not in [5, 14, 25, 45, 46, 47, 51, 53]: + logger.info("From Server: %s", packet.id) if self.server_protocol.handle_starbound_packets( packet): self.server_protocol.write(packet.original_data) From 4124334b5bace69245f89ba1c5eb2df28beb9645 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 10 Feb 2015 23:29:32 -0500 Subject: [PATCH 93/95] Commented out some of my debug lines. --- server.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server.py b/server.py index d447132..4113bdf 100644 --- a/server.py +++ b/server.py @@ -152,8 +152,8 @@ def string_received(self, packet): """ if 53 >= packet.id: # DEBUG - print all packet IDs going to client - if packet.id not in [14, 44, 45, 46, 47, 51, 53]: - logger.info("From Client: %s", packet.id) + # if packet.id not in [14, 44, 45, 46, 47, 51, 53]: + # logger.info("From Client: %s", packet.id) if self.handle_starbound_packets(packet): self.client_protocol.transport.write( packet.original_data) @@ -547,8 +547,8 @@ def string_received(self, packet): """ try: # DEBUG - print all packet IDs coming from client - if packet.id not in [5, 14, 25, 45, 46, 47, 51, 53]: - logger.info("From Server: %s", packet.id) + # if packet.id not in [5, 14, 25, 45, 46, 47, 51, 53]: + # logger.info("From Server: %s", packet.id) if self.server_protocol.handle_starbound_packets( packet): self.server_protocol.write(packet.original_data) From f5e3fae3bb59a42b5d614b76fee359b71ebd0e98 Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 10 Feb 2015 23:33:10 -0500 Subject: [PATCH 94/95] bring config.json.default up to speed. --- config/config.json.default | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/config/config.json.default b/config/config.json.default index 2fc90b4..45f36a6 100644 --- a/config/config.json.default +++ b/config/config.json.default @@ -94,23 +94,10 @@ "bad_packets": [ "CONNECT_WIRE", "DISCONNECT_ALL_WIRES", - "SWAP_IN_CONTAINER", "DAMAGE_TILE", "DAMAGE_TILE_GROUP", "MODIFY_TILE_LIST" ], - "bad_packets_mild": [ - "CONNECT_WIRE", - "DISCONNECT_ALL_WIRES", - "DAMAGE_TILE", - "DAMAGE_TILE_GROUP", - "MODIFY_TILE_LIST" - ], - "bad_packets_ship": [ - "ENTITY_INTERACT", - "OPEN_CONTAINER", - "CLOSE_CONTAINER" - ], "blacklist": [ "bomb", "bombblockexplosion", From b02e42a91d212ecf6990e9e2c7e23f2a1cdf91aa Mon Sep 17 00:00:00 2001 From: Kharidiron Date: Tue, 10 Feb 2015 23:56:45 -0800 Subject: [PATCH 95/95] Updated version number and Readme file. --- README.md | 56 ++++++++++++++++++++++++++----------------------------- server.py | 4 ++-- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index da7ed2a..4861d57 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,13 @@ With the built-in plugins (which are removable): * Join/quit announcements. * And more. +## Version 1.5 is here! -## Upgrading from older versions of StarryPy +With this most recent release, we are compatible with the current release of Starbound (Upbeat Giraffe). Any bugs found in the process, please open an issue ticket, so we can squash them as quickly as possible. -In version 1.4.x a new requirement "sqlite3" has been added to requirements.txt. -It is required to perform DB upgrade. Install manually with: pip install sqlite3 +## Upgrading from older versions of StarryPy +StarryPy 1.5 is **NOT** backwards compatible with older versions. As unfortunate as it is, we suggest wiping your database, and starting fresh. It will save a lot of headaches in the long run. ## Installation @@ -116,6 +117,13 @@ variables: on. * passthrough: **Make sure this is false.** It is an emergency off switch for StarryPy. + +In addition you may also want to setup + +* owner_uuid: This should be the UUID associated with whatever in-game character you want to have 'ownership' rights on the server. From there you can promote others to moderator, admin, or even owner as well. +* admin_ss: This is a password that unlocks the ability for Moderators, Admins and Owners to use commands on the server. This is a deadman switch system, meaning that you **will not be able to use privileged commands** if you do not have this password setup. Once you have set a password here, when logging into your server from Starbound, type this password in the `account` field. This is used **in addition** to your server password. +* log_level: This is, but default, set to `DEBUG`. If you want leaner logs, set it to `INFO`. If you want to see all the details going on in the background, set it to `VDEBUG`. +* irc settings: If you want chat replication to an IRC chatroom, setup your bot parameters here. A password is may not be required for all servers, but the added security isn't a bad idea. Finally, find starbound.config and change `gameport` to be exactly the same as `upstream_port` in config.json. @@ -134,7 +142,7 @@ Enter `python server.py` to start the proxy. StarryPy is nearly entirely plugin driven (our plugin manager is a plugin!), so there are quite a few built-in plugins. The truly important plugins are in the -core\_plugins folder. If you remove any of those, it's likely that most other +`core/` plugins folder. If you remove any of those, it's likely that most other plugins will break. We'll break them down by core plugin and normal plugin classes. @@ -180,11 +188,6 @@ prefixed with ## will be sent to moderators+ only. `Access: Everyone` This plugin simply announces whenever a player joins or quits the server. -#### Bouncer - -This plugin prevents non-registered users from building or destroying anything. It -is disabled by default. - #### Colored names This plugin displays color codes for each username depending on rank. The colors @@ -196,14 +199,12 @@ This plugin sends a Message of the Day on login. #### New Player Greeter -Greets first-time players on the server. Gives them a greeting (located in -new\_player\_message.txt) and gives them a pack of starter items (located in -starter\_items.txt). Default items are 200 `coalore` and 5 `alienburger`s. +Greets first-time players on the server. Gives them a greeting that can be configured in the config file and can also give them a pack of starter items. (200 Coal is currently included to give you a sample of the format expected.) #### Planet Protection This plugin protects specified planets against modification in any way. Currently -if a planet is protected only registered users may modify it. +if a planet is protected only those users who are the planet's protect list may make modifications. #### Plugin Manager @@ -212,9 +213,16 @@ that it's a plugin, you don't have to tell me. #### Warpy -This plugin provides various methods for warping players and ships around. +This plugin provides various methods for warping players around. + +#### PoI and Bookmarks + +These are two seperate plugins that do similar things. Every user has the ability to planets to their own personal bookmark list, allowing for fast return to the planet later. + +Points of Interest are setup by administrators for the whole community, allowing fast, fuel-free travel to those desintations. #### WebGUI + If activated, this will give you a web-GUI to administrate your StarryPy server. You can log in with your Character's name and the password you set as "ownerpassword" in the StarryPy config. ##### Config Parameters: @@ -231,11 +239,6 @@ If activated, this will give you a web-GUI to administrate your StarryPy server. * [jQuery-Knob](http://anthonyterrien.com/knob/), [D3](http://d3js.org/), [Select2](https://github.com/ivaynberg/select2), [Bootstrap Validator](https://github.com/nghuuphuoc/bootstrapvalidator), [TinyMCE](http://www.tinymce.com), [jQuery Timepicker](http://trentrichardson.com/examples/timepicker/), [xCharts](http://tenxer.github.io/xcharts/), [Fancybox](http://fancyapps.com/fancybox/), [Widen FineUploader](https://github.com/Widen/fine-uploader), [Datatables](http://datatables.net), jQuery-UI 1.10.4, [Twitter Bootstrap](http://getbootstrap.com), [Flot](www.flotcharts.org), [Fullcalendar](http://arshaw.com/fullcalendar), [Moment](http://momentjs.com/), [Justified Gallery](https://github.com/miromannino/Justified-Gallery), [Morris Charts](http://www.oesmith.co.uk/morris.js/) -#### More plugins - -Even more plugins can be found over at -[our plugin list](https://github.com/MrMarvin/StarryPy_plugins). - ## Plugin development There are several built-in plugins that you can derive inspiration from. The @@ -262,8 +265,9 @@ provide a link. ### None of the commands are working -You are likely in passthrough mode or connecting to the vanilla server. Check -config.json and ensure that passthrough is false. +You likely did not provide the admin_ss password. If the server is responding "You're not logged in, so I can't let you do that", then this is the case. Please check that you have the admin_ss password set, and that you are putting it in the `account` field at login. + +If you are seeing responses from the Starbound built-in commands, then you are either in passthrough mode, connecting directly to the vanilla server, or your account is in a foul state. For the first case, check config.json and ensure that passthrough is false. For the next, ensure you are indeed connecting to to the StarryPy server port, and not the vanilla server's. If you're account is fouled, have another moderator or admin kick you character. This seems to clear the bad sate. If you are running StarryPy on the same computer you're playing it from, it is likely it is using the gameport in starbound.config to connect to. To avoid this, @@ -286,17 +290,9 @@ We have quite a roadmap, here are some of the highlights you can expect in the next major version, and in the development branch before that if you're feeling brave: -* Spawn networks. Free transportation between admin-designated planets, so your - new players can get a leg up in the world. -* Loot rolling. So a rare item dropped and you don't think it's fair your friend - got it? Soon you'll be able to get good items without ending friendships and - going to prison on the inevitable murder charge. -* Lotteries. Because what is life without a little risk? * Creature spawning. Want to spawn a couple dozen bone dragons? So do we! * Internationalization. Translate plugins and core messages with ease to your preferred language. -* Role based access control Thought the mod/admin/owner distinction is useful, - having individual roles is our plan for the future. * Client filtering based on modded items. Though asset digests aren't supported right now, we want to do some minor filtering to keep out the riff-raff (if you as an admin want to.) @@ -311,7 +307,7 @@ issues page. We're absolutely happy to accept pull requests. There is a freenode channel called [##starbound-dev](http://webchat.freenode.net/?channels=##starbound-dev) -that we discuss our development on primarily. +that we discuss our development on primarily. We also have the channel [##starrypy](http://webchat.freenode.net/?channels=##starrypy) for discussion specific to our wrapper. Other than that, please report any bugs you find with the appropriate section of the debug.log file that is generated. diff --git a/server.py b/server.py index 006ab09..0c335c4 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,7 @@ from plugin_manager import PluginManager, route, FatalPluginError from utility_functions import build_packet -VERSION = "1.4.4" +VERSION = "1.5" VDEBUG_LVL = 9 @@ -756,4 +756,4 @@ def init_localization(): sys.exit() logger.info("Listening on port %s" % factory.config.bind_port) - reactor.run() \ No newline at end of file + reactor.run()