diff --git a/bin/camp-update.sh b/bin/camp-update.sh
index c5b64b6..30ec690 100755
--- a/bin/camp-update.sh
+++ b/bin/camp-update.sh
@@ -9,6 +9,9 @@ function do_git {
cd $1
git ls-remote --get-url
git pull
+ if [ -f .gitmodules ]; then
+ git pull --recurse-submodules
+ fi
cd ..
echo
}
diff --git a/bin/dropbox.py b/bin/dropbox.py
new file mode 100755
index 0000000..99830c3
--- /dev/null
+++ b/bin/dropbox.py
@@ -0,0 +1,1603 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) Dropbox, Inc.
+#
+# dropbox
+# Dropbox frontend script
+# This file is part of nautilus-dropbox 2020.03.04.
+#
+# nautilus-dropbox 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.
+#
+# nautilus-dropbox 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 nautilus-dropbox. If not, see .
+#
+from __future__ import with_statement
+
+import _thread
+import errno
+import locale
+import optparse
+import os
+import platform
+import shutil
+import socket
+import subprocess
+import sys
+import tarfile
+import tempfile
+import threading
+import time
+import traceback
+import urllib.request
+
+try:
+ import gpg
+ gpgme = None
+except ImportError:
+ gpg = None
+ # Still support gpgme for now. Remove this once we only support 17.04+.
+ try:
+ import gpgme
+ except ImportError:
+ gpgme = None
+
+from contextlib import closing, contextmanager
+from io import BytesIO
+from operator import methodcaller
+from os.path import relpath
+from posixpath import abspath, commonprefix, curdir, join, pardir, sep
+
+INFO = "Dropbox is the easiest way to share and store your files online. Want to learn more? Head to"
+LINK = "https://www.dropbox.com/"
+WARNING = "In order to use Dropbox, you must download the proprietary daemon."
+GPG_WARNING = "Note: python3-gpg (python3-gpgme for Ubuntu 16.10 and lower) is not installed, we will not be able to verify binary signatures."
+ERROR_CONNECTING = "Trouble connecting to Dropbox servers. Maybe your internet connection is down, or you need to set your http_proxy environment variable."
+ERROR_SIGNATURE = "Downloaded binary does not match Dropbox signature, aborting install."
+ERROR_INVALID_DROPBOX = "Could not start the Dropbox daemon. Make sure your computer meets the minimum requirements:\nhttps://www.dropbox.com/help/desktop-web/system-requirements#desktop"
+
+DOWNLOAD_LOCATION_FMT = "https://www.dropbox.com/download?plat=%s"
+SIGNATURE_LOCATION_FMT = "https://www.dropbox.com/download?plat=%s&signature=1"
+
+DOWNLOADING = "Downloading Dropbox... %d%%"
+UNPACKING = "Unpacking Dropbox... %d%%"
+
+PARENT_DIR = os.path.expanduser("~")
+DROPBOX_DIST_PATH = "%s/.dropbox-dist" % PARENT_DIR
+DROPBOXD_PATH = os.path.join(DROPBOX_DIST_PATH, "dropboxd")
+DESKTOP_FILE = "/usr/share/applications/dropbox.desktop"
+
+enc = locale.getpreferredencoding()
+
+# Available from https://linux.dropbox.com/fedora/rpm-public-key.asc
+DROPBOX_PUBLIC_KEY = b"""
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.1.0
+
+mQENBEt0ibEBCACv4hZRPqwtpU6z8+BB5YZU1a3yjEvg2W68+a6hEwxtCa2U++4dzQ+7EqaU
+q5ybQnwtbDdpFpsOi9x31J+PCpufPUfIG694/0rlEpmzl2GWzY8NqfdBFGGm/SPSSwvKbeNc
+FMRLu5neo7W9kwvfMbGjHmvUbzBUVpCVKD0OEEf1q/Ii0Qcekx9CMoLvWq7ZwNHEbNnij7ec
+nvwNlE2MxNsOSJj+hwZGK+tM19kuYGSKw4b5mR8IyThlgiSLIfpSBh1n2KX+TDdk9GR+57TY
+vlRu6nTPu98P05IlrrCP+KF0hYZYOaMvQs9Rmc09tc/eoQlN0kkaBWw9Rv/dvLVc0aUXABEB
+AAG0MURyb3Bib3ggQXV0b21hdGljIFNpZ25pbmcgS2V5IDxsaW51eEBkcm9wYm94LmNvbT6J
+ATYEEwECACAFAkt0ibECGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRD8kYszUESRLi/z
+B/wMscEa15rS+0mIpsORknD7kawKwyda+LHdtZc0hD/73QGFINR2P23UTol/R4nyAFEuYNsF
+0C4IAD6y4pL49eZ72IktPrr4H27Q9eXhNZfJhD7BvQMBx75L0F5gSQwuC7GdYNlwSlCD0AAh
+Qbi70VBwzeIgITBkMQcJIhLvllYo/AKD7Gv9huy4RLaIoSeofp+2Q0zUHNPl/7zymOqu+5Ox
+e1ltuJT/kd/8hU+N5WNxJTSaOK0sF1/wWFM6rWd6XQUP03VyNosAevX5tBo++iD1WY2/lFVU
+JkvAvge2WFk3c6tAwZT/tKxspFy4M/tNbDKeyvr685XKJw9ei6GcOGHD
+=5rWG
+-----END PGP PUBLIC KEY BLOCK-----
+"""
+
+
+def console_print(st="", f=sys.stdout, linebreak=True):
+ f.write(st)
+ if linebreak: f.write(os.linesep)
+
+def console_flush(f=sys.stdout):
+ f.flush()
+
+def yes_no_question(question):
+ while True:
+ console_print(question, linebreak=False)
+ console_print(" [y/n] ", linebreak=False)
+ console_flush()
+ text = input()
+ if text.lower().startswith("y"):
+ return True
+ elif text.lower().startswith("n"):
+ return False
+ else:
+ console_print("Sorry, I didn't understand that. Please type yes or no.")
+
+def plat():
+ if sys.platform.lower().startswith('linux'):
+ arch = platform.machine()
+ if (arch[0] == 'i' and
+ arch[1].isdigit() and
+ arch[2:4] == '86'):
+ plat = "x86"
+ elif arch == 'x86_64':
+ plat = arch
+ else:
+ FatalVisibleError("Platform not supported")
+ return "lnx.%s" % plat
+ else:
+ FatalVisibleError("Platform not supported")
+
+def is_dropbox_running():
+ pidfile = os.path.expanduser("~/.dropbox/dropbox.pid")
+
+ try:
+ with open(pidfile, "r") as f:
+ pid = int(f.read())
+ with open("/proc/%d/cmdline" % pid, "r") as f:
+ cmdline = f.read().lower()
+ except:
+ cmdline = ""
+
+ return "dropbox" in cmdline
+
+@contextmanager
+def gpg_context(keys):
+ gpg_conf_contents = b''
+ _gpghome = tempfile.mkdtemp(prefix='tmp.gpghome')
+
+ try:
+ os.environ['GNUPGHOME'] = _gpghome
+ fp = open(os.path.join(_gpghome, 'gpg.conf'), 'wb')
+ fp.write(gpg_conf_contents)
+ fp.close()
+ if gpg:
+ ctx = gpg.Context()
+ else:
+ ctx = gpgme.Context()
+
+ loaded = []
+ for key_file in keys:
+ if gpg:
+ ctx.op_import(key_file.read())
+ result = ctx.op_import_result()
+ key = ctx.get_key(result.imports[0].fpr)
+ else:
+ result = ctx.import_(key_file)
+ key = ctx.get_key(result.imports[0][0])
+ loaded.append(key)
+
+ ctx.signers = loaded
+
+ yield ctx
+ finally:
+ del os.environ['GNUPGHOME']
+ shutil.rmtree(_gpghome, ignore_errors=True)
+
+class SignatureVerifyError(Exception):
+ pass
+
+def verify_signature(key_file, sig_file, plain_file):
+ with gpg_context([key_file]) as ctx:
+ if gpg:
+ ctx.op_verify(sig_file.read(), plain_file.read(), None)
+ result = ctx.op_verify_result()
+ return result.signatures[0].status == 0
+ # gpgme exists
+ sigs = ctx.verify(sig_file, plain_file, None)
+ return sigs[0].status == None
+
+
+def download_file_chunk(url, buf):
+ opener = urllib.request.build_opener()
+ opener.addheaders = [('User-Agent', "DropboxLinuxDownloader/2020.03.04")]
+
+ with closing(opener.open(url)) as f:
+ size = int(f.info()['content-length'])
+ bufsize = int(max(size / 200, 4096))
+ progress = 0
+ yield (0, True)
+ while True:
+ try:
+ chunk = f.read(bufsize)
+ progress += len(chunk)
+ buf.write(chunk)
+ yield (float(progress)/size, True)
+ if progress == size:
+ break
+ except OSError as e:
+ if hasattr(e, 'errno') and e.errno == errno.EAGAIN:
+ # nothing left to read
+ yield (float(progress)/size, False)
+ else:
+ raise
+
+class DownloadState(object):
+ def __init__(self):
+ self.local_file = BytesIO()
+
+ def copy_data(self):
+ return download_file_chunk(DOWNLOAD_LOCATION_FMT % plat(), self.local_file)
+
+ def unpack(self):
+ # download signature
+ signature = BytesIO()
+ for _ in download_file_chunk(SIGNATURE_LOCATION_FMT % plat(), signature):
+ pass
+ signature.seek(0)
+ self.local_file.seek(0)
+
+ if gpg or gpgme:
+ if not verify_signature(BytesIO(DROPBOX_PUBLIC_KEY), signature, self.local_file):
+ raise SignatureVerifyError()
+
+ self.local_file.seek(0)
+ archive = tarfile.open(fileobj=self.local_file, mode='r:gz')
+ total_members = len(archive.getmembers())
+ for i, member in enumerate(archive.getmembers()):
+ filename = os.path.join(PARENT_DIR, member.name)
+ if os.path.exists(filename) and not os.path.isdir(filename):
+ os.unlink(filename)
+ archive.extract(member, PARENT_DIR)
+ yield member.name, i, total_members
+ archive.close()
+
+ def cancel(self):
+ if not self.local_file.closed:
+ self.local_file.close()
+
+ def is_dropbox_valid(self):
+ """
+ Validate that Dropbox runs, so we can show an error
+ message to the user if it doesn't work.
+
+ Returns True if Dropbox can run, false otherwise.
+ """
+ f = open("/dev/null", "w")
+ try:
+ a = subprocess.Popen([DROPBOXD_PATH, "/testrun", "0"], preexec_fn=os.setsid, cwd=os.path.expanduser("~"),
+ stderr=sys.stderr, stdout=f, close_fds=True)
+ except Exception as e:
+ print(e)
+ return False
+
+ # in seconds
+ interval = 0.5
+ wait_for = 30
+ for _ in range(int(wait_for / interval)):
+ ret_val = a.poll()
+ if ret_val is None:
+ time.sleep(interval)
+ continue
+ return ret_val == 0
+
+ return False
+
+
+def load_serialized_images():
+ global box_logo_pixbuf, window_icon
+ import gi
+ gi.require_version('GdkPixbuf', '2.0')
+ from gi.repository import GdkPixbuf
+ box_logo_pixbuf = GdkPixbuf.Pixbuf.new_from_data(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\xff\x1b\x00c\xff\xad\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xff\x02\x00d\xffn\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffp\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcb\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00c\xff\x8e\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00c\xff\x90\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xffN\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\xffP\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00d\xffR\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00d\xff\x92\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00c\xff\xce\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00b\xffr\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffn\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffp\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00e\xffQ\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00e\xffQ\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb0\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffp\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00d\xffp\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb0\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00d\xffp\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00c\xff\xb0\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', GdkPixbuf.Colorspace.RGB, True, 8, 64, 64, 256)
+ window_icon = GdkPixbuf.Pixbuf.new_from_data(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00b\xffN\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00b\xffN\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00b\xffN\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00b\xff\r\x00d\xff\x92\x00c\xff\xfd\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00d\xff\x92\x00c\xff\xfd\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xffe\x00d\xfff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xfff\x00d\xfff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\xff\x0b\x00b\xff\x8c\x00b\xff\xfc\x00b\xff\xfc\x00c\xff\x8d\x00t\xff\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00t\xff\x0b\x00b\xff\x8c\x00b\xff\xfc\x00b\xff\xfc\x00b\xff\x8c\x00t\xff\x0b\x00\x00\x00\x00\x00c\xffK\x00c\xff\xe0\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe1\x00e\xffL\x00e\xffL\x00c\xff\xe1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe1\x00e\xffL\x00d\xffT\x00c\xff\xe5\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe6\x00c\xffU\x00d\xffT\x00c\xff\xe6\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe6\x00d\xffT\x00\x00\x00\x00\x00m\xff\x0e\x00b\xff\x94\x00c\xff\xfd\x00c\xff\xfd\x00c\xff\x95\x00i\xff\x11\x00c\xffj\x00d\xffk\x00i\xff\x11\x00c\xff\x95\x00c\xff\xfd\x00c\xff\xfd\x00c\xff\x95\x00m\xff\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff7\x00d\xff8\x00d\xff.\x00b\xff\xc8\x00b\xff\xff\x00b\xff\xff\x00b\xff\xc8\x00g\xff/\x00f\xff7\x00f\xff7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\x7f\x00c\xff\xfb\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfb\x00d\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\xff \x00b\xff\xb6\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb7\x00d\xff!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffW\x00b\xff\xe7\x00b\xff\xe7\x00d\xffW\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff\x0f\x00p\xff\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', GdkPixbuf.Colorspace.RGB, True, 8, 16, 16, 64)
+
+GUI_AVAILABLE = os.environ.get("DISPLAY", '')
+
+if GUI_AVAILABLE:
+ def download():
+ import gi
+ gi.require_version('Gdk', '3.0')
+ gi.require_version('Gtk', '3.0')
+ import webbrowser
+
+ from gi.repository import Gdk, GObject, Gtk, Pango
+
+ GObject.threads_init()
+
+ load_serialized_images()
+
+ global FatalVisibleError
+ def FatalVisibleError(s):
+ error = Gtk.MessageDialog(parent = None,
+ flags = Gtk.DialogFlags.MODAL,
+ type = Gtk.MessageType.ERROR,
+ buttons = Gtk.ButtonsType.OK,
+ message_format = s)
+ error.set_title("Error")
+ error.run()
+ Gtk.main_quit()
+ sys.exit(-1)
+
+ class GeneratorTask(object):
+ def __init__(self, generator, loop_callback, on_done=None, on_exception=None):
+ self.generator = generator
+ self.loop_callback = loop_callback
+ self.on_done = on_done
+ self.on_exception = on_exception
+
+ def _run(self, *args, **kwargs):
+ self._stopped = False
+ try:
+ for ret in self.generator(*args, **kwargs):
+ if ret is None:
+ ret = ()
+ if not isinstance(ret, tuple):
+ ret = (ret,)
+ GObject.idle_add(self.loop_callback, *ret)
+
+ if self._stopped:
+ _thread.exit()
+ except Exception as e:
+ print(e)
+ if self.on_exception is not None:
+ GObject.idle_add(self.on_exception, e)
+ else:
+ if self.on_done is not None:
+ GObject.idle_add(self.on_done)
+
+ def start(self, *args, **kwargs):
+ t = threading.Thread(target=self._run, args=args, kwargs=kwargs)
+ t.setDaemon(True)
+ t.start()
+
+ def stop(self):
+ self._stopped = True
+
+ class DownloadDialog(Gtk.Dialog):
+ def handle_delete_event(self, wid, ev, data=None):
+ self.handle_cancel(wid)
+
+ def handle_dont_show_toggle(self, button, data=None):
+ reroll_autostart(not button.get_active())
+
+ def handle_cancel(self, button):
+ if self.task:
+ self.task.stop()
+ if self.download:
+ self.download.cancel()
+ Gtk.main_quit()
+ self.user_cancelled = True
+
+ def handle_ok(self, button):
+ # begin download
+ self.ok.hide()
+ self.download = DownloadState()
+
+ self.label.hide()
+ if self.dont_show_again_align is not None:
+ self.dont_show_again_align.hide()
+ self.progress.show()
+
+ def download_progress(progress, status):
+ if not status:
+ self.task.stop()
+ self.update_progress(DOWNLOADING, progress)
+
+ def finished():
+ self.update_progress(DOWNLOADING, 1.0)
+ self.unpack_dropbox()
+
+ def error(ex):
+ FatalVisibleError(ERROR_CONNECTING)
+
+ self.update_progress(DOWNLOADING, 0)
+ self.task = GeneratorTask(self.download.copy_data,
+ download_progress,
+ finished, error).start()
+
+ def update_progress(self, text, fraction):
+ self.progress.set_text(text % int(fraction*100))
+ self.progress.set_fraction(fraction)
+
+ def unpack_dropbox(self):
+ def unpack_progress(name, i, total):
+ self.update_progress(UNPACKING, float(i)/total)
+
+ def finished():
+ self.update_progress(UNPACKING, 1.0)
+ if not self.download.is_dropbox_valid():
+ FatalVisibleError(ERROR_INVALID_DROPBOX)
+ Gtk.main_quit()
+
+ def error(ex):
+ if isinstance(ex, SignatureVerifyError):
+ FatalVisibleError(ERROR_SIGNATURE)
+ else:
+ FatalVisibleError(ERROR_CONNECTING)
+
+ self.task = GeneratorTask(self.download.unpack,
+ unpack_progress,
+ finished, error).start()
+
+ def mouse_down(self, widget, event):
+ if self.hovering:
+ self.clicked_link = True
+
+ def mouse_up(self, widget, event):
+ if self.clicked_link:
+ webbrowser.open(LINK)
+ self.clicked_link = False
+
+ def label_motion(self, widget, event):
+ offx, offy = self.label.get_layout_offsets()
+ layout = self.label.get_layout()
+ index = layout.xy_to_index(int((offx+event.x)*Pango.SCALE),
+ int((offy+event.y)*Pango.SCALE))[1]
+ link_index = layout.get_text().find(LINK)
+ if index >= link_index and index < link_index+len(LINK):
+ self.hovering = True
+ self.label_box.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2))
+ else:
+ self.hovering = False
+ self.label_box.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.ARROW))
+
+
+ def __init__(self):
+ super(DownloadDialog, self).__init__(parent = None,
+ title = "Dropbox Installation")
+
+ self.download = None
+ self.hovering = False
+ self.clicked_link = False
+ self.user_cancelled = False
+ self.task = None
+
+ self.ok = ok = Gtk.Button(stock=Gtk.STOCK_OK)
+ ok.connect('clicked', self.handle_ok)
+ self.action_area.add(ok)
+ ok.show()
+
+ cancel = Gtk.Button(stock=Gtk.STOCK_CANCEL)
+ cancel.connect('clicked', self.handle_cancel)
+ self.action_area.add(cancel)
+ cancel.show()
+
+ self.connect('delete_event', self.handle_delete_event)
+
+ self.box_logo = Gtk.Image.new_from_pixbuf(box_logo_pixbuf)
+ self.box_logo.show()
+
+ self.set_icon(window_icon)
+
+ self.progress = Gtk.ProgressBar()
+ self.progress.set_property('width-request', 300)
+ self.progress.set_property('show-text', True)
+
+ self.label = Gtk.Label()
+ GPG_WARNING_MSG = ("\n\n" + GPG_WARNING) if not gpg and not gpgme else ""
+ self.label.set_markup('%s %s\n\n%s%s' % (INFO, LINK, WARNING, GPG_WARNING_MSG))
+ self.label.set_line_wrap(True)
+ self.label.set_property('width-request', 300)
+ self.label.show()
+
+ self.label_box = Gtk.EventBox()
+ self.label_box.add(self.label)
+ self.label_box.connect("button-release-event", self.mouse_up)
+ self.label_box.connect("button-press-event", self.mouse_down)
+ self.label_box.connect("motion-notify-event", self.label_motion)
+
+ self.label_box.show()
+ def on_realize(widget):
+ self.label_box.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
+ self.label_box.connect("realize", on_realize)
+
+ self.hbox = Gtk.HBox(spacing=10)
+ self.hbox.set_property('border-width',10)
+ self.hbox.pack_start(self.box_logo, False, False, 0)
+ self.hbox.pack_start(self.label_box, False, False, 0)
+ self.hbox.pack_start(self.progress, False, False, 0)
+ self.hbox.show()
+
+ self.vbox.add(self.hbox)
+
+ self.dont_show_again_align = None
+
+ try:
+ if can_reroll_autostart():
+ dont_show_again = Gtk.CheckButton.new_with_mnemonic("_Don't show this again")
+ dont_show_again.connect('toggled', self.handle_dont_show_toggle)
+ dont_show_again.show()
+
+ self.dont_show_again_align = Gtk.Alignment(xalign=1.0, yalign=0.0, xscale=0.0, yscale=0.0)
+ self.dont_show_again_align.add(dont_show_again)
+ self.dont_show_again_align.show()
+
+ hbox = Gtk.HBox()
+ hbox.set_property('border-width', 10)
+ hbox.pack_start(self.dont_show_again_align, True, True, 0)
+ hbox.show()
+
+ self.vbox.add(hbox)
+
+ self.set_resizable(False)
+ except:
+ traceback.print_exc()
+
+ self.ok.grab_focus()
+
+ dialog = DownloadDialog()
+ dialog.show()
+ Gtk.main()
+ if dialog.user_cancelled:
+ raise Exception("user cancelled download!!!")
+else:
+ def download():
+ global FatalVisibleError
+ def FatalVisibleError(s):
+ console_print("\nError: %s" % s, f=sys.stderr)
+ sys.exit(-1)
+
+
+ ESC = "\x1b"
+ save = ESC+"7"
+ unsave = ESC+"8"
+ erase_to_start = ESC+"[1K"
+ write = sys.stdout.write
+ flush = sys.stdout.flush
+
+ last_progress = [None, None]
+ def setprogress(text, frac):
+ if last_progress == [text, frac]:
+ return
+ if sys.stdout.isatty():
+ write(erase_to_start)
+ write(unsave)
+ console_print(text % int(100*frac), linebreak=not sys.stdout.isatty())
+ if sys.stdout.isatty():
+ flush()
+ last_progress[0], last_progress[1] = text, frac
+
+ console_print()
+ if sys.stdout.isatty():
+ write(save)
+ flush()
+ console_print("%s %s\n" % (INFO, LINK))
+ GPG_WARNING_MSG = ("\n%s" % GPG_WARNING) if not gpg and not gpgme else ""
+
+ if not yes_no_question("%s%s" % (WARNING, GPG_WARNING_MSG)):
+ return
+
+ download = DownloadState()
+
+ try:
+ for progress, status in download.copy_data():
+ if not status:
+ break
+ setprogress(DOWNLOADING, progress)
+ except Exception:
+ traceback.print_exc()
+ FatalVisibleError(ERROR_CONNECTING)
+ else:
+ setprogress(DOWNLOADING, 1.0)
+ console_print()
+ write(save)
+
+ try:
+ for _, i, total in download.unpack():
+ setprogress(UNPACKING, float(i)/total)
+ except SignatureVerifyError:
+ traceback.print_exc()
+ FatalVisibleError(ERROR_SIGNATURE)
+ except Exception:
+ traceback.print_exc()
+ FatalVisibleError(ERROR_CONNECTING)
+ else:
+ setprogress(UNPACKING, 1.0)
+
+ if not download.is_dropbox_valid():
+ FatalVisibleError(ERROR_INVALID_DROPBOX)
+
+ console_print()
+
+class CommandTicker(threading.Thread):
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self.stop_event = threading.Event()
+
+ def stop(self):
+ self.stop_event.set()
+
+ def run(self):
+ ticks = ['[. ]', '[.. ]', '[...]', '[ ..]', '[ .]', '[ ]']
+ i = 0
+ first = True
+ while True:
+ self.stop_event.wait(0.25)
+ if self.stop_event.isSet(): break
+ if i == len(ticks):
+ first = False
+ i = 0
+ if not first:
+ sys.stderr.write("\r%s\r" % ticks[i])
+ sys.stderr.flush()
+ i += 1
+ sys.stderr.flush()
+
+
+class DropboxCommand(object):
+ class CouldntConnectError(Exception): pass
+ class BadConnectionError(Exception): pass
+ class EOFError(Exception): pass
+ class CommandError(Exception): pass
+
+ def __init__(self, timeout=5):
+ self.s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.s.settimeout(timeout)
+ try:
+ self.s.connect(os.path.expanduser('~/.dropbox/command_socket'))
+ except socket.error:
+ raise DropboxCommand.CouldntConnectError()
+ self.f = self.s.makefile("rw", 4096)
+
+ def close(self):
+ self.f.close()
+ self.s.close()
+
+ def __readline(self):
+ try:
+ toret = self.f.readline().rstrip("\n")
+ except socket.error:
+ raise DropboxCommand.BadConnectionError()
+ if toret == '':
+ raise DropboxCommand.EOFError()
+ else:
+ return toret
+
+ # atttribute doesn't exist, i know what you want
+ def send_command(self, name, args):
+ self.f.write(name)
+ self.f.write("\n")
+ self.f.writelines(("\t".join([k] + ([v]
+ if isinstance(v, str) else
+ list(v))) + "\n")
+ for k,v in args.items())
+ self.f.write("done\n")
+
+ self.f.flush()
+
+ # Start a ticker
+ ticker_thread = CommandTicker()
+ ticker_thread.start()
+
+ # This is the potentially long-running call.
+ try:
+ ok = self.__readline() == "ok"
+ except KeyboardInterrupt:
+ raise DropboxCommand.BadConnectionError("Keyboard interruption detected")
+ finally:
+ # Tell the ticker to stop.
+ ticker_thread.stop()
+ ticker_thread.join()
+
+ if ok:
+ toret = {}
+ for i in range(21):
+ if i == 20:
+ raise Exception("close this connection!")
+
+ line = self.__readline()
+ if line == "done":
+ break
+
+ argval = line.split("\t")
+ toret[argval[0]] = argval[1:]
+
+ return toret
+ else:
+ problems = []
+ for i in range(21):
+ if i == 20:
+ raise Exception("close this connection!")
+
+ line = self.__readline()
+ if line == "done":
+ break
+
+ problems.append(line)
+
+ raise DropboxCommand.CommandError("\n".join(problems))
+
+ # this is the hotness, auto marshalling
+ def __getattr__(self, name):
+ try:
+ return super(DropboxCommand, self).__getattr__(name)
+ except:
+ def __spec_command(**kw):
+ return self.send_command(str(name), kw)
+ self.__setattr__(name, __spec_command)
+ return __spec_command
+
+commands = {}
+aliases = {}
+
+def command(meth):
+ global commands, aliases
+ assert meth.__doc__, "All commands need properly formatted docstrings (even %r!!)" % meth
+ if hasattr(meth, 'im_func'): # bound method, if we ever have one
+ meth = meth.im_func
+ commands[meth.__name__] = meth
+ meth_aliases = [str(alias) for alias in aliases.keys() if aliases[alias].__name__ == meth.__name__]
+ if meth_aliases:
+ meth.__doc__ += "\nAliases: %s" % ",".join(meth_aliases)
+ return meth
+
+def alias(name):
+ def decorator(meth):
+ global commands, aliases
+ assert name not in commands, "This alias is the name of a command."
+ aliases[name] = meth
+ return meth
+ return decorator
+
+def requires_dropbox_running(meth):
+ def newmeth(*n, **kw):
+ if is_dropbox_running():
+ return meth(*n, **kw)
+ else:
+ console_print("Dropbox isn't running!")
+ newmeth.__name__ = meth.__name__
+ newmeth.__doc__ = meth.__doc__
+ return newmeth
+
+def start_dropbox():
+ if os.access(DROPBOXD_PATH, os.X_OK):
+ f = open("/dev/null", "w")
+
+ # Fix indicator icon and menu on Unity environments. (LP: #1559249)
+ # Fix indicator icon and menu in Budgie environment. (LP: #1683051)
+ new_env = os.environ.copy()
+ current_env = os.environ.get("XDG_CURRENT_DESKTOP", '').split(":")
+ to_check = ['Unity', 'Budgie']
+ if any(word in to_check for word in current_env):
+ new_env['XDG_CURRENT_DESKTOP'] = 'Unity'
+
+ # we don't reap the child because we're gonna die anyway, let init do it
+ subprocess.Popen([DROPBOXD_PATH], preexec_fn=os.setsid, cwd=os.path.expanduser("~"),
+ stderr=sys.stderr, stdout=f, close_fds=True, env=new_env)
+
+ # in seconds
+ interval = 0.5
+ wait_for = 60
+ for _ in range(int(wait_for / interval)):
+ if is_dropbox_running():
+ return True
+ # back off from connect for a while
+ time.sleep(interval)
+
+ return False
+ else:
+ return False
+
+# Extracted and modified from os.cmd.Cmd
+def columnize(list, display_list=None, display_width=None):
+ if not list:
+ console_print("")
+ return
+
+ non_str = [i for i in range(len(list)) if not (isinstance(list[i], str))]
+ if non_str:
+ raise TypeError("list[i] not a string for i in %s" %
+ ", ".join(map(str, non_str)))
+
+ if not display_width:
+ d = os.popen('stty size', 'r').read().split()
+ if d:
+ display_width = int(d[1])
+ else:
+ for item in list:
+ console_print(item)
+ return
+
+ if not display_list:
+ display_list = list
+
+ size = len(list)
+ if size == 1:
+ console_print(display_list[0])
+ return
+
+ for nrows in range(1, len(list)):
+ ncols = (size+nrows-1) // nrows
+ colwidths = []
+ totwidth = -2
+ for col in range(ncols):
+ colwidth = 0
+ for row in range(nrows):
+ i = row + nrows*col
+ if i >= size:
+ break
+ x = list[i]
+ colwidth = max(colwidth, len(x))
+ colwidths.append(colwidth)
+ totwidth += colwidth + 2
+ if totwidth > display_width:
+ break
+ if totwidth <= display_width:
+ break
+ else:
+ nrows = len(list)
+ ncols = 1
+ colwidths = [0]
+ lines = []
+ for row in range(nrows):
+ texts = []
+ display_texts = []
+ for col in range(ncols):
+ i = row + nrows*col
+ if i >= size:
+ x = ""
+ y = ""
+ else:
+ x = list[i]
+ y = display_list[i]
+ texts.append(x)
+ display_texts.append(y)
+ while texts and not texts[-1]:
+ del texts[-1]
+ original_texts = texts[:]
+ for col in range(len(texts)):
+ texts[col] = texts[col].ljust(colwidths[col])
+ texts[col] = texts[col].replace(original_texts[col], display_texts[col])
+ line = " ".join(texts)
+ lines.append(line)
+ for line in lines:
+ console_print(line)
+
+@command
+def update(args):
+ """download latest version of Dropbox
+dropbox update
+
+Downloads the latest version of Dropbox. This should not be required
+normally, as Dropbox automatically updates itself.
+ """
+ download()
+
+@command
+@requires_dropbox_running
+@alias('stat')
+def filestatus(args):
+ """get current sync status of one or more files
+dropbox filestatus [-l] [-a] [FILE]...
+
+Prints the current status of each FILE.
+
+options:
+ -l --list Prints out information in a format similar to ls. Works best when your console supports color :)
+ -a --all Do not ignore entries starting with "."
+ """
+ global enc
+
+ oparser = optparse.OptionParser()
+ oparser.add_option("-l", "--list", action="store_true", dest="list")
+ oparser.add_option("-a", "--all", action="store_true", dest="all")
+ (options, args) = oparser.parse_args(args)
+
+ try:
+ with closing(DropboxCommand()) as dc:
+ if options.list:
+ # Listing.
+
+ # Separate directories from files.
+ if len(args) == 0:
+ dirs, nondirs = ["."], []
+ else:
+ dirs, nondirs = [], []
+
+ for a in args:
+ try:
+ (dirs if os.path.isdir(a) else nondirs).append(a)
+ except UnicodeDecodeError:
+ continue
+
+ if len(dirs) == 0 and len(nondirs) == 0:
+ #TODO: why?
+ exit(1)
+
+ dirs.sort(key=methodcaller('lower'))
+ nondirs.sort(key=methodcaller('lower'))
+
+ # Gets a string representation for a path.
+ def path_to_string(file_path):
+ if not os.path.exists(file_path):
+ path = "%s (File doesn't exist!)" % os.path.basename(file_path)
+ return (path, path)
+ try:
+ status = dc.icon_overlay_file_status(path=file_path).get('status', [None])[0]
+ except DropboxCommand.CommandError as e:
+ path = "%s (%s)" % (os.path.basename(file_path), e)
+ return (path, path)
+
+ env_term = os.environ.get('TERM','')
+ supports_color = (sys.stderr.isatty() and (
+ env_term.startswith('vt') or
+ env_term.startswith('linux') or
+ 'xterm' in env_term or
+ 'color' in env_term
+ )
+ )
+
+ # TODO: Test when you don't support color.
+ if not supports_color:
+ path = os.path.basename(file_path)
+ return (path, path)
+
+ if status == "up to date":
+ init, cleanup = "\x1b[32;1m", "\x1b[0m"
+ elif status == "syncing":
+ init, cleanup = "\x1b[36;1m", "\x1b[0m"
+ elif status == "unsyncable":
+ init, cleanup = "\x1b[41;1m", "\x1b[0m"
+ elif status == "selsync":
+ init, cleanup = "\x1b[37;1m", "\x1b[0m"
+ else:
+ init, cleanup = '', ''
+
+ path = os.path.basename(file_path)
+ return (path, "%s%s%s" % (init, path, cleanup))
+
+ # Prints a directory.
+ def print_directory(name):
+ clean_paths = []
+ formatted_paths = []
+ for subname in sorted(os.listdir(name), key=methodcaller('lower')):
+ if type(subname) != str:
+ continue
+
+ if not options.all and subname[0] == '.':
+ continue
+
+ try:
+ clean, formatted = path_to_string(os.path.abspath(os.path.join(name, subname)))
+ clean_paths.append(clean)
+ formatted_paths.append(formatted)
+ except (UnicodeEncodeError, UnicodeDecodeError):
+ continue
+
+ columnize(clean_paths, formatted_paths)
+
+ try:
+ if len(dirs) == 1 and len(nondirs) == 0:
+ print_directory(dirs[0])
+ else:
+ nondir_formatted_paths = []
+ nondir_clean_paths = []
+ for name in nondirs:
+ try:
+ clean, formatted = path_to_string(os.path.abspath(name))
+ nondir_clean_paths.append(clean)
+ nondir_formatted_paths.append(formatted)
+ except (UnicodeEncodeError, UnicodeDecodeError):
+ continue
+
+ if nondir_clean_paths:
+ columnize(nondir_clean_paths, nondir_formatted_paths)
+
+ if len(nondirs) == 0:
+ console_print(dirs[0] + ":")
+ print_directory(dirs[0])
+ dirs = dirs[1:]
+
+ for name in dirs:
+ console_print()
+ console_print(name + ":")
+ print_directory(name)
+
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ else:
+ if len(args) == 0:
+ args = [name for name in sorted(os.listdir("."), key=methodcaller('lower')) if type(name) == str]
+ if len(args) == 0:
+ # Bail early if there's nothing to list to avoid crashing on indent below
+ console_print("")
+ return
+ indent = max(len(st)+1 for st in args)
+ for file in args:
+
+ try:
+ if type(file) is not str:
+ file = file.decode(enc)
+ fp = os.path.abspath(file)
+ except (UnicodeEncodeError, UnicodeDecodeError):
+ continue
+ if not os.path.exists(fp):
+ console_print("%-*s %s" % \
+ (indent, file+':', "File doesn't exist"))
+ continue
+
+ try:
+ status = dc.icon_overlay_file_status(path=fp).get('status', ['unknown'])[0]
+ console_print("%-*s %s" % (indent, file+':', status))
+ except DropboxCommand.CommandError as e:
+ console_print("%-*s %s" % (indent, file+':', e))
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+@requires_dropbox_running
+def ls(args):
+ """list directory contents with current sync status
+dropbox ls [FILE]...
+
+This is an alias for filestatus -l
+ """
+ return filestatus(["-l"] + args)
+
+@command
+@requires_dropbox_running
+def puburl(args):
+ """get public url of a file in your Dropbox's public folder
+dropbox puburl FILE
+
+Prints out a public url for FILE (which must be in your public folder).
+ """
+ if len(args) != 1:
+ console_print(puburl.__doc__,linebreak=False)
+ return
+
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ console_print(dc.get_public_link(path=os.path.abspath(args[0])).get('link', ['No Link'])[0])
+ except DropboxCommand.CommandError as e:
+ console_print("Couldn't get public url: " + str(e))
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+@requires_dropbox_running
+def sharelink(args):
+ """get a shared link for a file in your Dropbox
+dropbox sharelink FILE
+
+Prints out a shared link for FILE.
+ """
+ if len(args) != 1:
+ console_print(sharelink.__doc__, linebreak=False)
+ return
+
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ path = os.path.abspath(args[0])
+ link = dc.get_shared_link(path=path).get('link', ['No link'])[0]
+ console_print(link)
+ except DropboxCommand.CommandError as e:
+ console_print("Couldn't get shared link: " + str(e))
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+@requires_dropbox_running
+def proxy(args):
+ """set proxy settings for Dropbox
+dropbox proxy MODE [TYPE] [HOST] [PORT] [USERNAME] [PASSWORD]
+
+Set proxy settings for Dropbox.
+
+MODE - one of "none", "auto", "manual"
+TYPE - one of "http", "socks4", "socks5" (only valid with "manual" mode)
+HOST - proxy hostname (only valid with "manual" mode)
+PORT - proxy port (only valid with "manual" mode)
+USERNAME - (optional) proxy username (only valid with "manual" mode)
+PASSWORD - (optional) proxy password (only valid with "manual" mode)
+ """
+ mode = None
+ type_ = None
+ if len(args) >= 1:
+ mode = args[0].lower()
+ if len(args) >= 2:
+ type_ = args[1].lower()
+
+ if (len(args) == 0 or
+ mode not in ['none', 'auto', 'manual'] or
+ (mode == 'manual' and len(args) not in (4, 6)) or
+ (mode != 'manual' and len(args) != 1) or
+ (mode == 'manual' and type_ not in ['http', 'socks4', 'socks5'])):
+ # Print help
+ console_print(proxy.__doc__, linebreak=False)
+ return
+
+ ARGS = ['mode', 'type', 'host', 'port', 'username', 'password']
+
+ # Load the args into a dictionary
+ kwargs = dict(zip(ARGS, args))
+
+ # Re-set these two because they were coerced to lower case
+ kwargs['mode'] = mode
+ if type_:
+ kwargs['type'] = type_
+
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ dc.set_proxy_settings(**kwargs)
+ console_print('set')
+ except DropboxCommand.CommandError as e:
+ console_print("Couldn't set proxy: " + str(e))
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+@requires_dropbox_running
+def throttle(args):
+ """set bandwidth limits for Dropbox
+dropbox throttle DOWNLOAD UPLOAD
+
+Set bandwidth limits for file sync.
+
+DOWNLOAD - either "unlimited" or a manual limit in KB/s
+UPLOAD - one of "unlimited", "auto", or a manual limit in KB/s
+ """
+ if len(args) != 2:
+ console_print(throttle.__doc__, linebreak=False)
+ return
+
+ downlimit = args[0].lower()
+ uplimit = args[1].lower()
+
+ download_limit = None
+ download_mode = None
+ if downlimit == 'unlimited':
+ download_mode = downlimit
+ else:
+ try:
+ download_limit = int(downlimit)
+ download_mode = 'manual'
+ except ValueError:
+ console_print(throttle.__doc__, linebreak=False)
+ return
+
+ upload_limit = None
+ upload_mode = None
+ if uplimit in ['unlimited', 'auto']:
+ upload_mode = uplimit
+ else:
+ try:
+ upload_limit = int(uplimit)
+ upload_mode = 'manual'
+ except ValueError:
+ console_print(throttle.__doc__, linebreak=False)
+ return
+
+ kwargs = {
+ 'download_mode': download_mode,
+ 'upload_mode': upload_mode,
+ }
+ if download_limit:
+ kwargs['download_limit'] = str(download_limit)
+ if upload_limit:
+ kwargs['upload_limit'] = str(upload_limit)
+
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ dc.set_bandwidth_limits(**kwargs)
+ console_print('set')
+ except DropboxCommand.CommandError as e:
+ console_print("Couldn't set bandwidth limits: " + str(e))
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+@requires_dropbox_running
+def status(args):
+ """get current status of the dropboxd
+dropbox status
+
+Prints out the current status of the Dropbox daemon.
+ """
+ if len(args) != 0:
+ console_print(status.__doc__,linebreak=False)
+ return
+
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ lines = dc.get_dropbox_status()['status']
+ if len(lines) == 0:
+ console_print('Idle')
+ else:
+ for line in lines:
+ console_print(line)
+ grab_link_url_if_necessary()
+ except KeyError:
+ console_print("Couldn't get status: daemon isn't responding")
+ except DropboxCommand.CommandError as e:
+ console_print("Couldn't get status: " + str(e))
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+def running(argv):
+ """return whether Dropbox is running
+dropbox running
+
+Returns 1 if running, and 0 if not running.
+ """
+ return int(is_dropbox_running())
+
+@command
+@requires_dropbox_running
+def stop(args):
+ """stop dropboxd
+dropbox stop
+
+Stops the Dropbox daemon.
+ """
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ dc.tray_action_hard_exit()
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+#returns true if link is necessary
+def grab_link_url_if_necessary():
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ link_url = dc.needs_link().get("link_url", None)
+ if link_url is not None:
+ console_print("To link this computer to a Dropbox account, visit the following url:\n%s" % link_url[0])
+ return True
+ else:
+ return False
+ except DropboxCommand.CommandError:
+ pass
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+
+@command
+@requires_dropbox_running
+def lansync(argv):
+ """enables or disables LAN sync
+dropbox lansync [y/n]
+
+options:
+ y Dropbox will use LAN sync (default)
+ n Dropbox will not use LAN sync
+ """
+ if len(argv) != 1:
+ console_print(lansync.__doc__, linebreak=False)
+ return
+
+ s = argv[0].lower()
+ if s.startswith('y') or s.startswith('-y'):
+ should_lansync = True
+ elif s.startswith('n') or s.startswith('-n'):
+ should_lansync = False
+ else:
+ should_lansync = None
+
+ if should_lansync is None:
+ console_print(lansync.__doc__,linebreak=False)
+ else:
+ with closing(DropboxCommand()) as dc:
+ dc.set_lan_sync(lansync='enabled' if should_lansync else 'disabled')
+
+
+@command
+@requires_dropbox_running
+def exclude(args):
+ """ignores/excludes a directory from syncing
+dropbox exclude [list]
+dropbox exclude add [DIRECTORY] [DIRECTORY] ...
+dropbox exclude remove [DIRECTORY] [DIRECTORY] ...
+
+"list" prints a list of directories currently excluded from syncing.
+"add" adds one or more directories to the exclusion list, then
+resynchronizes Dropbox.
+"remove" removes one or more directories from the exclusion list, then
+resynchronizes Dropbox.
+
+With no arguments, executes "list".
+
+Any specified path must be within Dropbox.
+ """
+ if len(args) == 0:
+ try:
+ with closing(DropboxCommand()) as dc:
+ try:
+ lines = [relpath(path) for path in dc.get_ignore_set()['ignore_set']]
+ lines.sort()
+ if len(lines) == 0:
+ console_print('No directories are being ignored.')
+ else:
+ console_print('Excluded: ')
+ for line in lines:
+ console_print(str(line))
+ except KeyError:
+ console_print("Couldn't get ignore set: daemon isn't responding")
+ except DropboxCommand.CommandError as e:
+ if e.args[0].startswith("No command exists by that name"):
+ console_print("This version of the client does not support this command.")
+ else:
+ console_print("Couldn't get ignore set: " + str(e))
+ except DropboxCommand.BadConnectionError:
+ console_print("Dropbox isn't responding!")
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+ elif len(args) == 1 and args[0] == "list":
+ exclude([])
+ elif len(args) >= 2:
+ sub_command = args[0]
+ paths = args[1:]
+ absolute_paths = [os.path.abspath(path) for path in paths]
+ if sub_command == "add":
+ try:
+ with closing(DropboxCommand(timeout=None)) as dc:
+ try:
+ result = dc.ignore_set_add(paths=absolute_paths)
+ if result["ignored"]:
+ console_print("Excluded: ")
+ lines = [relpath(path) for path in result["ignored"]]
+ for line in lines:
+ console_print(str(line))
+ except KeyError:
+ console_print("Couldn't add ignore path: daemon isn't responding")
+ except DropboxCommand.CommandError as e:
+ if e.args[0].startswith("No command exists by that name"):
+ console_print("This version of the client does not support this command.")
+ else:
+ console_print("Couldn't get ignore set: " + str(e))
+ except DropboxCommand.BadConnectionError as e:
+ console_print("Dropbox isn't responding! [%s]" % e)
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+ elif sub_command == "remove":
+ try:
+ with closing(DropboxCommand(timeout=None)) as dc:
+ try:
+ result = dc.ignore_set_remove(paths=absolute_paths)
+ if result["removed"]:
+ console_print("No longer excluded: ")
+ lines = [relpath(path) for path in result["removed"]]
+ for line in lines:
+ console_print(str(line))
+ except KeyError:
+ console_print("Couldn't remove ignore path: daemon isn't responding")
+ except DropboxCommand.CommandError as e:
+ if e.args[0].startswith("No command exists by that name"):
+ console_print("This version of the client does not support this command.")
+ else:
+ console_print("Couldn't get ignore set: " + str(e))
+ except DropboxCommand.BadConnectionError as e:
+ console_print("Dropbox isn't responding! [%s]" % e)
+ except DropboxCommand.EOFError:
+ console_print("Dropbox daemon stopped.")
+ except DropboxCommand.CouldntConnectError:
+ console_print("Dropbox isn't running!")
+ else:
+ console_print(exclude.__doc__, linebreak=False)
+ return
+ else:
+ console_print(exclude.__doc__, linebreak=False)
+ return
+
+@command
+def start(argv):
+ """start dropboxd
+dropbox start [-i]
+
+Starts the Dropbox daemon, dropboxd. If dropboxd is already running,
+this will do nothing.
+
+options:
+ -i --install auto install dropboxd if not available on the system
+ """
+
+ should_install = "-i" in argv or "--install" in argv
+
+ # first check if dropbox is already running
+ if is_dropbox_running():
+ if not grab_link_url_if_necessary():
+ console_print("Dropbox is already running!")
+ return
+
+ console_print("Starting Dropbox...", linebreak=False)
+ console_flush()
+ if not start_dropbox():
+ if not should_install:
+ console_print()
+ console_print("The Dropbox daemon is not installed!")
+ console_print("Run \"dropbox start -i\" to install the daemon")
+ return
+
+ # install dropbox!!!
+ try:
+ download()
+ except:
+ traceback.print_exc()
+ else:
+ if GUI_AVAILABLE:
+ start_dropbox()
+ console_print("Done!")
+ else:
+ if start_dropbox():
+ if not grab_link_url_if_necessary():
+ console_print("Done!")
+ else:
+ if not grab_link_url_if_necessary():
+ console_print("Done!")
+
+
+def can_reroll_autostart():
+ return ".config" in os.listdir(os.path.expanduser('~'))
+
+def reroll_autostart(should_autostart):
+ home_dir = os.path.expanduser('~')
+ contents = os.listdir(home_dir)
+
+ # UBUNTU
+ if ".config" in contents:
+ autostart_dir = os.path.join(home_dir, ".config", "autostart")
+ autostart_link = os.path.join(autostart_dir, "dropbox.desktop")
+ if should_autostart:
+ if os.path.exists(DESKTOP_FILE):
+ if not os.path.exists(autostart_dir):
+ os.makedirs(autostart_dir)
+ shutil.copyfile(DESKTOP_FILE, autostart_link)
+ elif os.path.exists(autostart_link):
+ os.remove(autostart_link)
+
+
+
+@command
+def autostart(argv):
+ """automatically start Dropbox at login
+dropbox autostart [y/n]
+
+options:
+ n Dropbox will not start automatically at login
+ y Dropbox will start automatically at login (default)
+
+Note: May only work on current Ubuntu distributions.
+ """
+ if len(argv) != 1:
+ console_print(''.join(autostart.__doc__.split('\n', 1)[1:]))
+ return
+
+ s = argv[0].lower()
+ if s.startswith('y') or s.startswith('-y'):
+ should_autostart = True
+ elif s.startswith('n') or s.startswith('-n'):
+ should_autostart = False
+ else:
+ should_autostart = None
+
+ if should_autostart is None:
+ console_print(autostart.__doc__,linebreak=False)
+ else:
+ reroll_autostart(should_autostart)
+
+@command
+def version(argv):
+ """print version information for Dropbox
+dropbox version
+
+Prints the version information for the Dropbox proprietary daemon, if
+it's installed, and the Dropbox command-line interface.
+ """
+ dropbox_daemon_version = "Not installed"
+ try:
+ with open(os.path.join(DROPBOX_DIST_PATH, 'VERSION')) as f:
+ dropbox_daemon_version = f.read().strip()
+ except OSError:
+ pass
+
+ console_print("Dropbox daemon version: %s" % dropbox_daemon_version)
+ console_print("Dropbox command-line interface version: 2020.03.04")
+
+@command
+def help(argv):
+ """provide help
+dropbox help [COMMAND]
+
+With no arguments, print a list of commands and a short description of
+each. With a command, print descriptive help on how to use the
+command.
+ """
+ if not argv:
+ return usage()
+ for command in commands:
+ if command == argv[0]:
+ console_print(commands[command].__doc__.split('\n', 1)[1].strip())
+ return
+ for alias in aliases:
+ if alias == argv[0]:
+ console_print(aliases[alias].__doc__.split('\n', 1)[1].strip())
+ return
+ console_print("unknown command '%s'" % argv[0], f=sys.stderr)
+
+def usage():
+ console_print("Dropbox command-line interface\n")
+ console_print("commands:\n")
+ console_print("Note: use dropbox help to view usage for a specific command.\n")
+ out = []
+ for command in commands:
+ out.append((command, commands[command].__doc__.splitlines()[0]))
+ out.sort(key=lambda x: x[0])
+ spacing = max(len(o[0])+3 for o in out)
+ for o in out:
+ console_print(" %-*s%s" % (spacing, o[0], o[1]))
+
+def main(argv):
+ global commands
+
+ # now we need to find out if one of the commands are in the
+ # argv list, and if so split the list at the point to
+ # separate the argv list at that point
+ cut = None
+ for i in range(len(argv)):
+ if argv[i] in commands or argv[i] in aliases:
+ cut = i
+ break
+
+ if cut == None:
+ usage()
+ os._exit(0)
+ return
+
+ # lol no options for now
+ globaloptionparser = optparse.OptionParser()
+ globaloptionparser.parse_args(argv[0:i])
+
+ # now dispatch and run
+ result = None
+ if argv[i] in commands:
+ result = commands[argv[i]](argv[i+1:])
+ elif argv[i] in aliases:
+ result = aliases[argv[i]](argv[i+1:])
+
+ # flush, in case output is rerouted to a file.
+ console_flush()
+
+ # done
+ return result
+
+if __name__ == "__main__":
+ ret = main(sys.argv)
+ if ret is not None:
+ sys.exit(ret)
diff --git a/bin/gits-checkup.sh b/bin/gits-checkup.sh
deleted file mode 100755
index 206f708..0000000
--- a/bin/gits-checkup.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-
-function do_git {
- echo $1
- cd $1
- git ls-remote --get-url | tee -a $HOME/Gits/gits.lst
- git status
- cd ..
- echo
-}
-
-function do_merc {
- echo $1
- cd $1
- ht heads
- cd ..
- echo
-}
-
-function do_svn {
- echo $1
- cd $1
- svn status
- cd ..
- echo
-}
-
-function do_dir {
- echo $1
- echo "-----------------"
- for i in *
- do
- if [ -d $i ]; then
- if [ -d $i/.git ]; then
- do_git $i
- elif [ -d $i/.hg ]; then
- do_merc $i
- elif [ -d $i/.svn ]; then
- do_svn $i
- else
- cd $i
- do_dir $i
- cd ..
- fi
- fi
- done
-}
-
-if [ -d $HOME/Gits ]; then
- cd $HOME/Gits
- echo "Git Repositories:"
- echo "================="
- cat /dev/null > gits.lst
- do_dir .
- echo "================="
- echo -n "Total: "
- wc -l gits.lst
- echo "================="
- if [ `hostname` != "babylon5" ]; then
- scp -P 2829 babylon5.probestar.com:~/Gits/gits-master.lst .
- sort gits.lst > stig.lst
- mv stig.lst gits.lst
- sort gits-master.lst > stug.lst
- mv stug.lst gits-master.lst
- diff -bw gits-master.lst gits.lst
- fi
- echo "================="
-fi
diff --git a/bin/gits-cleanup.sh b/bin/gits-cleanup.sh
deleted file mode 100755
index 5478e83..0000000
--- a/bin/gits-cleanup.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-
-function do_git {
- echo $1
- cd $1
- git ls-remote --get-url | tee -a $HOME/Gits/gits.lst
- git status
- git checkout -- .
- git pull
- cd ..
- echo
-}
-
-function do_merc {
- echo $1
- cd $1
- ht heads
- cd ..
- echo
-}
-
-function do_svn {
- echo $1
- cd $1
- svn status
- cd ..
- echo
-}
-
-function do_dir {
- echo $1
- echo "-----------------"
- for i in *
- do
- if [ -d $i ]; then
- if [ -d $i/.git ]; then
- do_git $i
- elif [ -d $i/.hg ]; then
- do_merc $i
- elif [ -d $i/.svn ]; then
- do_svn $i
- else
- cd $i
- do_dir $i
- cd ..
- fi
- fi
- done
-}
-
-if [ -d $HOME/Gits ]; then
- cd $HOME/Gits
- echo "Git Repositories:"
- echo "================="
- cat /dev/null > gits.lst
- do_dir .
- echo "================="
- echo -n "Total: "
- wc -l gits.lst
- echo "================="
- if [ `hostname` != "babylon5" ]; then
- scp -P 2829 babylon5.probestar.com:~/Gits/gits-master.lst .
- sort gits.lst > stig.lst
- mv stig.lst gits.lst
- sort gits-master.lst > stug.lst
- mv stug.lst gits-master.lst
- diff -bw gits-master.lst gits.lst
- fi
- echo "================="
-fi
diff --git a/bin/gits-update.sh b/bin/gits-update.sh
deleted file mode 100755
index d5fdea0..0000000
--- a/bin/gits-update.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-
-function do_git {
- echo $1
- cd $1
- git ls-remote --get-url | tee -a $HOME/Gits/gits.lst
- git pull
- cd ..
- echo
-}
-
-function do_dir {
- echo $1
- echo "-----------------"
- for i in *
- do
- if [ -d $i ]; then
- if [ -d $i/.git ]; then
- do_git $i
- else
- cd $i
- do_dir $i
- cd ..
- fi
- fi
- done
-}
-
-if [ -d $HOME/Gits ]; then
- cd $HOME/Gits
- echo "Git Repositories:"
- echo "================="
- cat /dev/null > gits.lst
- do_dir .
- echo "================="
- echo -n "Total: "
- wc -l gits.lst
- echo "================="
- if [ `hostname` == "babylon5" ]; then
- sort gits.lst > gits-master.lst
- else
- scp -P 2829 babylon5.probestar.com:~/Gits/gits-master.lst .
- sort gits.lst > stig.lst
- mv stig.lst gits.lst
- sort gits-master.lst > stug.lst
- mv stug.lst gits-master.lst
- diff -bw gits-master.lst gits.lst
- fi
- echo "================="
-fi
-
diff --git a/bin/ntcna-update.sh b/bin/ntcna-update.sh
index 56d8b36..8fcaf86 100755
--- a/bin/ntcna-update.sh
+++ b/bin/ntcna-update.sh
@@ -5,6 +5,9 @@ function do_git {
cd $1
git ls-remote --get-url
git pull
+ if [ -f .gitmodules ]; then
+ git pull --recurse-submodules
+ fi
cd ..
echo
}
diff --git a/bin/pstar-update.sh b/bin/pstar-update.sh
index 03e9029..2a546c5 100755
--- a/bin/pstar-update.sh
+++ b/bin/pstar-update.sh
@@ -5,6 +5,9 @@ function do_git {
cd $1
git ls-remote --get-url
git pull
+ if [ -f .gitmodules ]; then
+ git pull --recurse-submodules
+ fi
cd ..
echo
}
diff --git a/bin/xgps b/bin/xgps
deleted file mode 100755
index b5ff2fc..0000000
--- a/bin/xgps
+++ /dev/null
@@ -1,978 +0,0 @@
-#! /usr/bin/python
-# -*- coding: UTF-8
-'''
-xgps -- test client for gpsd
-
-usage: xgps [-D level] [-hV?] [-l degmfmt] [-u units] [-r rotation]
- [server[:port[:device]]]
-'''
-
-# This file is Copyright (c) 2010 by the GPSD project
-# BSD terms apply: see the file COPYING in the distribution root for details.
-#
-# This code runs compatibly under Python 2 and 3.x for x >= 2.
-# Preserve this property!
-from __future__ import absolute_import, print_function, division
-
-import math
-import socket
-import sys
-import time
-
-import gps
-import gps.clienthelpers
-
-import cairo
-
-# Gtk3 imports. Gtk3 requires the require_version(), which then causes
-# pylint to complain about the subsequent "non-top" imports.
-import gi
-gi.require_version('Gtk', '3.0')
-from gi.repository import GObject # pylint: disable=wrong-import-position
-from gi.repository import Gtk # pylint: disable=wrong-import-position
-from gi.repository import Gdk # pylint: disable=wrong-import-position
-
-gui_about = '''\
-This is xgps, a test client for the gpsd daemon.
-
-By Eric S. Raymond for the GPSD project, December 2009
-'''
-
-# Use our own MAXCHANNELS value, due to the tradeoff between max sats and
-# the window size. Ideally, this should be dynamic.
-MAXCHANNELS = 20
-
-# how to sort the Satellite List
-# some of ("PRN","el","az","ss","used") with optional '-' to reverse sort
-# by default, used at the top, then sort PRN
-SKY_VIEW_SORT_FIELDS = ('-used', 'PRN')
-
-
-class unit_adjustments(object):
- "Encapsulate adjustments for unit systems."
-
- def __init__(self, units=None):
- self.altfactor = 1.0
- self.altunits = "m"
- self.speedfactor = gps.MPS_TO_KPH
- self.speedunits = "kph"
- if units is None:
- units = gps.clienthelpers.gpsd_units()
- if units in (gps.clienthelpers.unspecified, gps.clienthelpers.imperial,
- "imperial", "i"):
- pass
- elif units in (gps.clienthelpers.nautical, "nautical", "n"):
- self.altfactor = gps.METERS_TO_FEET
- self.altunits = "ft"
- self.speedfactor = gps.MPS_TO_KNOTS
- self.speedunits = "knots"
- elif units in (gps.clienthelpers.metric, "metric", "m"):
- self.altfactor = 1.0
- self.altunits = "m"
- self.speedfactor = gps.MPS_TO_KPH
- self.speedunits = "kph"
- else:
- raise ValueError # Should never happen
-
-
-def fit_to_grid(x, y, line_width):
- "Adjust coordinates to produce sharp lines."
- if line_width % 1.0 != 0:
- # Can't have sharp lines for non-integral line widths.
- return float(x), float(y) # Be consistent about returning floats
- if line_width % 2 == 0:
- # Round to a pixel corner.
- return round(x), round(y)
- else:
- # Round to a pixel center.
- return int(x) + 0.5, int(y) + 0.5
-
-
-def fit_circle_to_grid(x, y, radius, line_width):
- """Adjust circle coordinates and radius to produce sharp horizontal
- and vertical tangents."""
- r = radius
- x1, y1 = fit_to_grid(x - r, y - r, line_width)
- x2, y2 = fit_to_grid(x + r, y + r, line_width)
- x, y = (x1 + x2) / 2, (y1 + y2) / 2
- r = (x2 - x1 + y2 - y1) / 4
- return x, y, r
-
-
-class SkyView(Gtk.DrawingArea):
- "Satellite skyview, encapsulates pygtk's draw-on-expose behavior."
- # See
- HORIZON_PAD = 40 # How much whitespace to leave around horizon
- SAT_RADIUS = 5 # Diameter of satellite circle
-
- def __init__(self, rotate=0.0):
- Gtk.DrawingArea.__init__(self)
- # GObject.GObject.__init__(self)
- self.set_size_request(400, 400)
- self.cr = None # New cairo context for each expose event
- self.step_of_grid = 30 # default step of polar grid
- self.connect('size-allocate', self.on_size_allocate)
- self.connect('draw', self.on_draw)
- self.satellites = []
- self.center_x = self.center_y = self.radius = None
- self.rotate = rotate
-
- def on_size_allocate(self, _unused, allocation):
- width = allocation.width
- height = allocation.height
- x = width // 2
- y = height // 2
- r = (min(width, height) - SkyView.HORIZON_PAD) // 2
- x, y, r = fit_circle_to_grid(x, y, r, 1)
- self.center_x = x
- self.center_y = y
- self.radius = r
-
- def set_color(self, spec):
- "Set foreground color for drawing."
- gdkcolor = Gdk.color_parse(spec)
- r = gdkcolor.red / 65535.0
- g = gdkcolor.green / 65535.0
- b = gdkcolor.blue / 65535.0
- self.cr.set_source_rgb(r, g, b)
-
- def draw_circle(self, x, y, radius, filled=False):
- "Draw a circle centered on the specified midpoint."
- lw = self.cr.get_line_width()
- r = int(2 * radius + 0.5) // 2
-
- x, y, r = fit_circle_to_grid(x, y, radius, lw)
-
- self.cr.arc(x, y, r, 0, math.pi * 2.0)
- self.cr.close_path()
-
- if filled:
- self.cr.fill()
- else:
- self.cr.stroke()
-
- def draw_line(self, x1, y1, x2, y2):
- "Draw a line between specified points."
- lw = self.cr.get_line_width()
- x1, y1 = fit_to_grid(x1, y1, lw)
- x2, y2 = fit_to_grid(x2, y2, lw)
-
- self.cr.move_to(x1, y1)
- self.cr.line_to(x2, y2)
-
- self.cr.stroke()
-
- def draw_square(self, x, y, radius, filled=False):
- "Draw a square centered on the specified midpoint."
- lw = self.cr.get_line_width()
- x1, y1 = fit_to_grid(x - radius, y - radius, lw)
- x2, y2 = fit_to_grid(x + radius, y + radius, lw)
-
- self.cr.rectangle(x1, y1, x2 - x1, y2 - y1)
-
- if filled:
- self.cr.fill()
- else:
- self.cr.stroke()
-
- def draw_string(self, x, y, text, centered=True):
- "Draw a text on the skyview."
- self.cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_BOLD)
- self.cr.set_font_size(10)
-
- if centered:
- extents = self.cr.text_extents(text)
- # width / 2 + x_bearing
- x -= extents[2] / 2 + extents[0]
- # height / 2 + y_bearing
- y -= extents[3] / 2 + extents[1]
-
- self.cr.move_to(x, y)
- self.cr.show_text(text)
- self.cr.new_path()
-
- def pol2cart(self, az, el):
- "Polar to Cartesian coordinates within the horizon circle."
- az = (az - self.rotate) % 360.0
- az *= (math.pi / 180) # Degrees to radians
- # Exact spherical projection would be like this:
- # el = sin((90.0 - el) * DEG_2_RAD);
- el = ((90.0 - el) / 90.0)
- xout = self.center_x + math.sin(az) * el * self.radius
- yout = self.center_y - math.cos(az) * el * self.radius
- return (xout, yout)
-
- def on_draw(self, widget, _unused):
- self.cr = widget.get_window().cairo_create()
-
- self.cr.set_line_width(1)
-
- self.cr.set_source_rgb(0, 0, 0)
- self.cr.paint()
-
- self.cr.set_source_rgb(1, 1, 1)
- # The zenith marker
- self.draw_circle(self.center_x, self.center_y, 6, filled=False)
-
- # The horizon circle
- if self.step_of_grid == 45:
- # The circle corresponding to 45 degrees elevation.
- # There are two ways we could plot this. Projecting the sphere
- # on the display plane, the circle would have a diameter of
- # sin(45) ~ 0.7. But the naive linear mapping, just splitting
- # the horizon diameter in half, seems to work better visually.
- self.draw_circle(self.center_x, self.center_y, self.radius / 2,
- filled=False)
- elif self.step_of_grid == 30:
- self.draw_circle(self.center_x, self.center_y, self.radius * 2 / 3,
- filled=False)
- self.draw_circle(self.center_x, self.center_y, self.radius / 3,
- filled=False)
- self.draw_circle(self.center_x, self.center_y, self.radius,
- filled=False)
-
- (x1, y1) = self.pol2cart(0, 0)
- (x2, y2) = self.pol2cart(180, 0)
- self.draw_line(x1, y1, x2, y2)
-
- (x1, y1) = self.pol2cart(90, 0)
- (x2, y2) = self.pol2cart(270, 0)
- self.draw_line(x1, y1, x2, y2)
-
- # The compass-point letters
- (x, y) = self.pol2cart(0, -5)
- self.draw_string(x, y, "N")
- (x, y) = self.pol2cart(90, -5)
- self.draw_string(x, y, "E")
- (x, y) = self.pol2cart(180, -5)
- self.draw_string(x, y, "S")
- (x, y) = self.pol2cart(270, -5)
- self.draw_string(x, y, "W")
-
- # The satellites
- self.cr.set_line_width(2)
- for sat in self.satellites:
- if sat.az == 0 and sat.el == 0:
- continue # Skip satellites with unknown position
- (x, y) = self.pol2cart(sat.az, sat.el)
- if sat.ss < 10:
- self.set_color("Gray")
- elif sat.ss < 30:
- self.set_color("Red")
- elif sat.ss < 35:
- self.set_color("Yellow")
- elif sat.ss < 40:
- self.set_color("Green3")
- else:
- self.set_color("Green1")
- if gps.is_sbas(sat.PRN):
- self.draw_square(x, y, SkyView.SAT_RADIUS, sat.used)
- else:
- self.draw_circle(x, y, SkyView.SAT_RADIUS, sat.used)
-
- self.cr.set_source_rgb(1, 1, 1)
- self.draw_string(x + SkyView.SAT_RADIUS,
- y + (SkyView.SAT_RADIUS * 2), str(sat.PRN),
- centered=False)
-
- self.cr = None
-
- def redraw(self, satellites):
- "Redraw the skyview."
- self.satellites = satellites
- self.queue_draw()
-
-
-class NoiseView(object):
- "Encapsulate view object for watching noise statistics."
- COLUMNS = 2
- ROWS = 4
- noisefields = (
- # First column
- ("Time", "time"),
- ("Latitude", "lat"),
- ("Longitude", "lon"),
- ("Altitude", "alt"),
- # Second column
- ("RMS", "rms"),
- ("Major", "major"),
- ("Minor", "minor"),
- ("Orient", "orient"),
- )
-
- def __init__(self):
- self.widget = Gtk.Table(NoiseView.COLUMNS, NoiseView.ROWS, False)
- self.noisewidgets = []
- for i in range(len(NoiseView.noisefields)):
- colbase = (i // NoiseView.ROWS) * 2
- label = Gtk.Label(label=NoiseView.noisefields[i][0] + ": ")
- # Wacky way to force right alignment
- label.set_alignment(xalign=1, yalign=0.5)
- self.widget.attach(
- label, colbase, colbase + 1,
- i % NoiseView.ROWS, i % NoiseView.ROWS + 1)
- entry = Gtk.Entry()
- # The right size for the ISO8601 timestamp
- entry.set_width_chars(20)
- entry.set_text("n/a")
- self.widget.attach(
- entry, colbase + 1, colbase + 2,
- i % NoiseView.ROWS, i % NoiseView.ROWS + 1)
- self.noisewidgets.append((NoiseView.noisefields[i][1], entry))
-
- def update(self, noise):
- "Update the GPGST data fields."
- for (attrname, widget) in self.noisewidgets:
- if hasattr(noise, attrname):
- widget.set_text(str(getattr(noise, attrname)))
- else:
- widget.set_text("n/a")
-
-
-class MaidenheadView(object):
- "Encapsulate view object for watching Maidenhead grid location."
-
- def __init__(self):
- self.widget = Gtk.Entry()
- self.widget.set_editable(False)
-
- def update(self, tpv):
- if ((tpv.mode >= gps.MODE_2D
- and hasattr(tpv, "lat")
- and hasattr(tpv, "lon"))):
- self.widget.set_text(gps.clienthelpers.maidenhead(tpv.lat,
- tpv.lon))
- else:
- return self.widget.set_text("n/a")
-
-
-class AISView(object):
- "Encapsulate store and view objects for watching AIS data."
- AIS_ENTRIES = 10
- DWELLTIME = 360
-
- def __init__(self, deg_type):
- "Initialize the store and view."
- self.deg_type = deg_type
- self.name_to_mmsi = {}
- self.named = {}
- self.store = Gtk.ListStore(str, str, str, str, str, str)
- self.widget = Gtk.ScrolledWindow()
- self.widget.set_policy(Gtk.PolicyType.AUTOMATIC,
- Gtk.PolicyType.AUTOMATIC)
- self.view = Gtk.TreeView(model=self.store)
- self.widget.set_size_request(-1, 300)
- self.widget.add_with_viewport(self.view)
-
- for (i, label) in enumerate(('#', 'Name:', 'Callsign:',
- 'Destination:', "Lat/Lon:",
- "Information")):
- column = Gtk.TreeViewColumn(label)
- renderer = Gtk.CellRendererText()
- column.pack_start(renderer, expand=True)
- column.add_attribute(renderer, 'text', i)
- self.view.append_column(column)
-
- def enter(self, ais, name):
- "Add a named object (ship or station) to the store."
- if ais.mmsi in self.named:
- return False
- else:
- ais.entry_time = time.time()
- self.named[ais.mmsi] = ais
- self.name_to_mmsi[name] = ais.mmsi
- # Garbage-collect old entries
- try:
- for i in range(len(self.store)):
- here = self.store.get_iter(i)
- name = self.store.get_value(here, 1)
- mmsi = self.name_to_mmsi[name]
- if ((self.named[mmsi].entry_time
- < time.time() - AISView.DWELLTIME)):
- del self.named[mmsi]
- if name in self.name_to_mmsi:
- del self.name_to_mmsi[name]
- self.store.remove(here)
- except (ValueError, KeyError): # Invalid TreeIters throw these
- pass
- return True
-
- def latlon(self, lat, lon):
- "Latitude/longitude display in nice format."
- if lat < 0:
- latsuff = "S"
- elif lat > 0:
- latsuff = "N"
- else:
- latsuff = ""
- lat = abs(lat)
- lat = gps.clienthelpers.deg_to_str(self.deg_type, lat)
- if lon < 0:
- lonsuff = "W"
- elif lon > 0:
- lonsuff = "E"
- else:
- lonsuff = ""
- lon = abs(lon)
- lon = gps.clienthelpers.deg_to_str(gps.clienthelpers.deg_ddmmss, lon)
- return lat + latsuff + "/" + lon + lonsuff
-
- def update(self, ais):
- "Update the AIS data fields."
- if ais.type in (1, 2, 3, 18):
- if ais.mmsi in self.named:
- for i in range(len(self.store)):
- here = self.store.get_iter(i)
- name = self.store.get_value(here, 1)
- if name in self.name_to_mmsi:
- mmsi = self.name_to_mmsi[name]
- if mmsi == ais.mmsi:
- latlon = self.latlon(ais.lat, ais.lon)
- self.store.set_value(here, 4, latlon)
- elif ais.type == 4:
- if self.enter(ais, ais.mmsi):
- where = self.latlon(ais.lat, ais.lon)
- self.store.prepend(
- (ais.type, ais.mmsi, "(shore)", ais.timestamp, where,
- ais.epfd_text))
- elif ais.type == 5:
- if self.enter(ais, ais.shipname):
- self.store.prepend(
- (ais.type, ais.shipname, ais.callsign, ais.destination,
- "", ais.shiptype))
- elif ais.type == 12:
- sender = ais.mmsi
- if sender in self.named:
- sender = self.named[sender].shipname
- recipient = ais.dest_mmsi
- if ((recipient in self.named
- and hasattr(self.named[recipient], "shipname"))):
- recipient = self.named[recipient].shipname
- self.store.prepend(
- (ais.type, sender, "", recipient, "", ais.text))
- elif ais.type == 14:
- sender = ais.mmsi
- if sender in self.named:
- sender = self.named[sender].shipname
- self.store.prepend(
- (ais.type, sender, "", "(broadcast)", "", ais.text))
- elif ais.type in (19, 24):
- if self.enter(ais, ais.shipname):
- self.store.prepend(
- (ais.type, ais.shipname, "(class B)", "", "",
- ais.shiptype_text))
- elif ais.type == 21:
- if self.enter(ais, ais.name):
- where = self.latlon(ais.lat, ais.lon)
- self.store.prepend(
- (ais.type, ais.name, "(%s navaid)" % ais.epfd_text,
- "", where, ais.aid_type_text))
-
-
-class Base(object):
- COLUMNS = 3
- ROWS = 7
- gpsfields = (
- # First column
- ("Time", lambda s, r: s.update_time(r)),
- ("Latitude", lambda s, r: s.update_latitude(r)),
- ("Longitude", lambda s, r: s.update_longitude(r)),
- ("Altitude", lambda s, r: s.update_altitude(r)),
- ("Speed", lambda s, r: s.update_speed(r)),
- ("Climb", lambda s, r: s.update_climb(r)),
- ("Track", lambda s, r: s.update_track(r)),
- # Second column
- ("Status", lambda s, r: s.update_status(r)),
- ("EPX", lambda s, r: s.update_err(r, "epx")),
- ("EPY", lambda s, r: s.update_err(r, "epy")),
- ("EPV", lambda s, r: s.update_err(r, "epv")),
- ("EPS", lambda s, r: s.update_err_speed(r, "eps")),
- ("EPC", lambda s, r: s.update_err_speed(r, "epc")),
- ("EPD", lambda s, r: s.update_err_degrees(r, "epd")),
- )
-
- def __init__(self, deg_type, rotate=0.0, target=""):
- self.deg_type = deg_type
- self.rotate = rotate
- self.conversions = unit_adjustments()
- self.saved_mode = -1
- self.ais_latch = False
- self.noise_latch = False
-
- self.window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
- if not self.window.get_display():
- raise Exception("Can't open display")
- if len(target):
- target = " " + target
- self.window.set_title("xgps" + target)
- self.window.connect("delete-event", self.delete_event)
- self.window.set_resizable(False)
-
- vbox = Gtk.VBox(False, 0)
- self.window.add(vbox)
-
- self.window.connect("destroy", lambda _unused: Gtk.main_quit())
-
- self.uimanager = Gtk.UIManager()
- self.accelgroup = self.uimanager.get_accel_group()
- self.window.add_accel_group(self.accelgroup)
- self.actiongroup = Gtk.ActionGroup('xgps')
- self.actiongroup.add_actions(
- [('Quit', Gtk.STOCK_QUIT, '_Quit', None,
- 'Quit the Program', lambda _unused: Gtk.main_quit()),
- ('File', None, '_File'),
- ('View', None, '_View'),
- ('Units', None, '_Units'),
- ('Step of grid', None, '_Step of grid')])
- self.actiongroup.add_toggle_actions(
- [('Skyview', None, '_Skyview', 's',
- 'Enable Skyview', self.view_toggle),
- ('Responses', None, '_Responses', 'r',
- 'Enable Response Reports', self.view_toggle),
- ('GPS', None, '_GPS Data', 'g',
- 'Enable GPS Data', self.view_toggle),
- ('Noise', None, '_Noise Statistics', 'n',
- 'Enable Noise Statistics', self.view_toggle),
- ('Maidenhead', None, '_Maidenhead', 'm',
- 'Enable Maidenhead locator', self.view_toggle),
- ('AIS', None, '_AIS Data', 'a',
- 'Enable AIS Data', self.view_toggle),
- ])
- self.actiongroup.add_radio_actions(
- [('Imperial', None, '_Imperial', 'i',
- 'Imperial units', 0),
- ('Nautical', None, '_Nautical', 'n',
- 'Nautical units', 1),
- ('Metric', None, '_Metric', 'm',
- 'Metric Units', 2),
- ], 2, lambda a, _unused: self.set_units(
- ['i', 'n', 'm'][a.get_current_value()]))
- self.actiongroup.add_radio_actions(
- [('30deg', None, '30°', None, '30°', 30),
- ('45deg', None, '45°', None, '45°', 45),
- ('Off', None, 'Off', None, 'Off', 0),
- ], 30, lambda a, _unused: self.set_step_of_grid(
- a.get_current_value()))
- self.uimanager.insert_action_group(self.actiongroup, 0)
- self.uimanager.add_ui_from_string('''
-
-
-
-
-
-
-
-
-''')
- self.uimanager.get_widget('/MenuBar/View/Skyview').set_active(True)
- self.uimanager.get_widget('/MenuBar/View/Responses').set_active(True)
- self.uimanager.get_widget('/MenuBar/View/GPS').set_active(True)
- self.uimanager.get_widget('/MenuBar/View/Noise').set_active(True)
- self.uimanager.get_widget('/MenuBar/View/Maidenhead').set_active(True)
- self.uimanager.get_widget('/MenuBar/View/AIS').set_active(True)
- menubar = self.uimanager.get_widget('/MenuBar')
- vbox.pack_start(menubar, expand=False, fill=True, padding=0)
-
- self.satbox = Gtk.HBox(False, 0)
- vbox.add(self.satbox)
-
- skyframe = Gtk.Frame(label="Satellite List")
- self.satbox.add(skyframe)
-
- self.satlist = Gtk.ListStore(str, str, str, str, str)
- view = Gtk.TreeView(model=self.satlist)
-
- for (i, label) in enumerate(('PRN:', 'Elev:', 'Azim:', 'SNR:',
- 'Used:')):
- column = Gtk.TreeViewColumn(label)
- renderer = Gtk.CellRendererText()
- column.pack_start(renderer, expand=True)
- column.add_attribute(renderer, 'text', i)
- view.append_column(column)
-
- self.row_iters = []
- for i in range(MAXCHANNELS):
- self.satlist.append(["", "", "", "", ""])
- self.row_iters.append(self.satlist.get_iter(i))
-
- skyframe.add(view)
-
- viewframe = Gtk.Frame(label="Skyview")
- self.satbox.add(viewframe)
- self.skyview = SkyView(self.rotate)
- viewframe.add(self.skyview)
-
- self.rawdisplay = Gtk.Entry()
- self.rawdisplay.set_editable(False)
- vbox.add(self.rawdisplay)
-
- self.dataframe = Gtk.Frame(label="GPS data")
- datatable = Gtk.Table(Base.COLUMNS, Base.ROWS, False)
- self.dataframe.add(datatable)
- gpswidgets = []
- for i in range(len(Base.gpsfields)):
- colbase = (i // Base.ROWS) * 2
- label = Gtk.Label(label=Base.gpsfields[i][0] + ": ")
- # Wacky way to force right alignment
- label.set_alignment(xalign=1, yalign=0.5)
- datatable.attach(label, colbase, colbase + 1,
- i % Base.ROWS, i % Base.ROWS + 1)
- entry = Gtk.Entry()
- # The right size for the ISO8601 timestamp
- entry.set_width_chars(20)
- entry.set_text("n/a")
- datatable.attach(entry, colbase + 1, colbase + 2,
- i % Base.ROWS, i % Base.ROWS + 1)
- gpswidgets.append(entry)
- vbox.add(self.dataframe)
-
- self.noisebox = Gtk.HBox(False, 0)
- vbox.add(self.noisebox)
- noiseframe = Gtk.Frame(label="Noise Statistics")
- self.noisebox.add(noiseframe)
- self.noiseview = NoiseView()
- noiseframe.add(self.noiseview.widget)
-
- self.gsbox = Gtk.HBox(False, 0)
- vbox.add(self.gsbox)
- gsframe = Gtk.Frame(label="Maidenhead Grid Square")
- self.gsbox.add(gsframe)
- self.gsview = MaidenheadView()
- gsframe.add(self.gsview.widget)
-
- self.aisbox = Gtk.HBox(False, 0)
- vbox.add(self.aisbox)
- aisframe = Gtk.Frame(label="AIS Data")
- self.aisbox.add(aisframe)
- self.aisview = AISView(self.deg_type)
- aisframe.add(self.aisview.widget)
-
- self.window.show_all()
- # Hide the Noise Statistics window until user selects it.
- self.uimanager.get_widget('/MenuBar/View/Noise').set_active(False)
- self.noisebox.hide()
- # Hide the Maidenhead window until user selects it.
- self.uimanager.get_widget('/MenuBar/View/Maidenhead').set_active(False)
- self.gsbox.hide()
- # Hide the AIS window until user selects it.
- self.uimanager.get_widget('/MenuBar/View/AIS').set_active(False)
- self.aisbox.hide()
-
- self.view_name_to_widget = {
- "Skyview": self.satbox,
- "Responses": self.rawdisplay,
- "GPS": self.dataframe,
- "Noise": self.noisebox,
- "Maidenhead": self.gsbox,
- "AIS": self.aisbox}
-
- # Discard field labels and associate data hooks with their widgets
- Base.gpsfields = [(label_hook_widget[0][1], label_hook_widget[1])
- for label_hook_widget
- in zip(Base.gpsfields, gpswidgets)]
-
- def view_toggle(self, action):
- # print("View toggle:", action.get_active(), action.get_name())
- if hasattr(self, 'view_name_to_widget'):
- if action.get_active():
- self.view_name_to_widget[action.get_name()].show()
- else:
- self.view_name_to_widget[action.get_name()].hide()
- # The effect we're after is to make the top-level window
- # resize itself to fit when we show or hide widgets.
- # This is undocumented magic to do that.
- self.window.resize(1, 1)
-
- def set_satlist_field(self, row, column, value):
- "Set a specified field in the satellite list."
- try:
- self.satlist.set_value(self.row_iters[row], column, str(value))
- except IndexError:
- sys.stderr.write("xgps: channel = %d, MAXCHANNELS = %d\n"
- % (row, MAXCHANNELS))
-
- def delete_event(self, _widget, _event, _data=None):
- Gtk.main_quit()
- return False
-
- # State updates
-
- def update_time(self, data):
- if hasattr(data, "time"):
- # str() just in case we get an old-style float.
- return str(data.time)
- else:
- return "n/a"
-
- def update_latitude(self, data):
- if data.mode >= gps.MODE_2D and hasattr(data, "lat"):
- lat = gps.clienthelpers.deg_to_str(self.deg_type, abs(data.lat))
- if data.lat < 0:
- ns = 'S'
- else:
- ns = 'N'
- return "%s %s" % (lat, ns)
- else:
- return "n/a"
-
- def update_longitude(self, data):
- if data.mode >= gps.MODE_2D and hasattr(data, "lon"):
- lon = gps.clienthelpers.deg_to_str(self.deg_type, abs(data.lon))
- if data.lon < 0:
- ew = 'W'
- else:
- ew = 'E'
- return "%s %s" % (lon, ew)
- else:
- return "n/a"
-
- def update_altitude(self, data):
- if data.mode >= gps.MODE_3D and hasattr(data, "alt"):
- return "%.3f %s" % (
- data.alt * self.conversions.altfactor,
- self.conversions.altunits)
- else:
- return "n/a"
-
- def update_speed(self, data):
- if hasattr(data, "speed"):
- return "%.3f %s" % (
- data.speed * self.conversions.speedfactor,
- self.conversions.speedunits)
- else:
- return "n/a"
-
- def update_climb(self, data):
- if hasattr(data, "climb"):
- return "%.3f %s" % (
- data.climb * self.conversions.speedfactor,
- self.conversions.speedunits)
- else:
- return "n/a"
-
- def update_track(self, data):
- if hasattr(data, "track"):
- return gps.clienthelpers.deg_to_str(self.deg_type, abs(data.track))
- else:
- return "n/a"
-
- def update_err(self, data, errtype):
- if hasattr(data, errtype):
- return "%.3f %s" % (
- getattr(data, errtype) * self.conversions.altfactor,
- self.conversions.altunits)
- else:
- return "n/a"
-
- def update_err_speed(self, data, errtype):
- if hasattr(data, errtype):
- return "%.3f %s" % (
- getattr(data, errtype) * self.conversions.speedfactor,
- self.conversions.speedunits)
- else:
- return "n/a"
-
- def update_err_degrees(self, data, errtype):
- if hasattr(data, errtype):
- return "%.3f °" % (getattr(data, errtype))
- else:
- return "n/a"
-
- def update_status(self, data):
- if data.mode == gps.MODE_2D:
- status = "2D FIX"
- elif data.mode == gps.MODE_3D:
- status = "3D FIX"
- else:
- status = "NO FIX"
-
- if hasattr(data, 'status') and data.status == gps.STATUS_DGPS_FIX:
- status += " DIFF"
- if data.mode != self.saved_mode:
- self.last_transition = time.time()
- self.saved_mode = data.mode
- return status + " (%d secs)" % (time.time() - self.last_transition)
-
- def update_gpsdata(self, tpv):
- "Update the GPS data fields."
- # the first 14 fields are updated using TPV data
- for (hook, widget) in Base.gpsfields[:14]:
- if hook: # Remove this guard when we have all hooks
- widget.set_text(hook(self, tpv))
- self.gsview.update(tpv)
-
- def update_skyview(self, data):
- "Update the satellite list and skyview."
- if hasattr(data, 'satellites'):
- satellites = data.satellites
- for fld in reversed(SKY_VIEW_SORT_FIELDS):
- rev = (fld[0] == '-')
- if rev:
- fld = fld[1:]
- satellites = sorted(
- satellites[:],
- key=lambda x: x[fld], reverse=rev)
-
- for (i, satellite) in enumerate(satellites):
- self.set_satlist_field(i, 0, satellite.PRN)
- self.set_satlist_field(i, 1, satellite.el)
- self.set_satlist_field(i, 2, satellite.az)
- self.set_satlist_field(i, 3, satellite.ss)
- yesno = 'N'
- if satellite.used:
- yesno = 'Y'
- self.set_satlist_field(i, 4, yesno)
- for i in range(len(satellites), MAXCHANNELS):
- for j in range(0, 5):
- self.set_satlist_field(i, j, "")
- self.skyview.redraw(satellites)
-
- # Preferences
-
- def set_units(self, system):
- "Change the display units."
- self.conversions = unit_adjustments(system)
-
- def set_step_of_grid(self, system):
- "Change the step of grid."
- self.skyview.step_of_grid = system
-
- # I/O monitoring and gtk housekeeping
-
- def watch(self, daemon, device):
- "Set up monitoring of a daemon instance."
- self.daemon = daemon
- self.device = device
- GObject.io_add_watch(daemon.sock, GObject.IO_IN, self.handle_response)
- GObject.io_add_watch(daemon.sock, GObject.IO_ERR, self.handle_hangup)
- GObject.io_add_watch(daemon.sock, GObject.IO_HUP, self.handle_hangup)
-
- def handle_response(self, source, condition):
- "Handle ordinary I/O ready condition from the daemon."
- if self.daemon.read() == -1:
- self.handle_hangup(source, condition)
- if self.daemon.valid & gps.PACKET_SET:
- if ((self.device
- and "device" in self.daemon.data
- and self.device != self.daemon.data["device"])):
- return True
- self.rawdisplay.set_text(self.daemon.response.strip())
- if self.daemon.data["class"] == "SKY":
- self.update_skyview(self.daemon.data)
- elif self.daemon.data["class"] == "TPV":
- self.update_gpsdata(self.daemon.data)
- elif self.daemon.data["class"] == "GST":
- self.noiseview.update(self.daemon.data)
- if not self.noise_latch:
- self.noise_latch = True
- self.uimanager.get_widget(
- '/MenuBar/View/Noise').set_active(True)
- self.noisebox.show()
- elif self.daemon.data["class"] == "AIS":
- self.aisview.update(self.daemon.data)
- if not self.ais_latch:
- self.ais_latch = True
- self.uimanager.get_widget(
- '/MenuBar/View/AIS').set_active(True)
- self.aisbox.show()
-
- return True
-
- def handle_hangup(self, _source, _condition):
- "Handle hangup condition from the daemon."
- w = Gtk.MessageDialog(parent=self.window,
- type=Gtk.MessageType.ERROR,
- flags=Gtk.DialogFlags.DESTROY_WITH_PARENT,
- buttons=Gtk.ButtonsType.CANCEL)
- w.connect("destroy", lambda _unused: Gtk.main_quit())
- w.set_markup("gpsd has stopped sending data.")
- w.run()
- Gtk.main_quit()
- return True
-
- def main(self):
- Gtk.main()
-
-if __name__ == "__main__":
- try:
- import getopt
- (options, arguments) = getopt.getopt(sys.argv[1:], "D:hl:u:r:V?",
- ['verbose'])
- debug = 0
- degreefmt = 'd'
- unit_system = None
- rotate = 0.0
- for (opt, val) in options:
- if opt in '-D':
- debug = int(val)
- elif opt == '-l':
- degreeformat = val
- elif opt == '-u':
- unit_system = val
- elif opt == '-r':
- try:
- rotate = float(val)
- except ValueError:
- rotate = 0.0
- elif opt in ('-?', '-h', '--help'):
- print(__doc__)
- sys.exit(0)
- elif opt == 'V':
- sys.stderr.write("xgps 1.0\n")
- sys.exit(0)
-
- degreefmt = {'d': gps.clienthelpers.deg_dd,
- 'm': gps.clienthelpers.deg_ddmm,
- 's': gps.clienthelpers.deg_ddmmss}[degreefmt]
-
- (host, port, device) = ("localhost", gps.GPSD_PORT, None)
- if len(arguments):
- args = arguments[0].split(":")
- if len(args) >= 1 and args[0]:
- host = args[0]
- if len(args) >= 2 and args[1]:
- port = args[1]
- if len(args) >= 3:
- device = args[2]
- target = ":".join(arguments[0:])
- else:
- target = ""
-
- base = Base(deg_type=degreefmt, rotate=rotate, target=target)
- base.set_units(unit_system)
- try:
- daemon = gps.gps(host=host,
- port=port,
- mode=gps.WATCH_ENABLE | gps.WATCH_JSON
- | gps.WATCH_SCALED,
- verbose=debug)
- base.watch(daemon, device)
- base.main()
- except socket.error:
- w = Gtk.MessageDialog(parent=base.window,
- type=Gtk.MessageType.ERROR,
- flags=Gtk.DialogFlags.DESTROY_WITH_PARENT,
- buttons=Gtk.ButtonsType.CANCEL)
- w.set_markup("gpsd is not running.")
- w.run()
- w.destroy()
- except KeyboardInterrupt:
- pass
diff --git a/sbin/github-load.sh b/sbin/github-load.sh
index 5cab0f2..58a2e2d 100755
--- a/sbin/github-load.sh
+++ b/sbin/github-load.sh
@@ -4,22 +4,27 @@
cd $HOME
mkdir bin misc tmp Projects Gits
+# remember token
+git config --global credential.helper cache
+echo "97453163f195ae988657fc1ef4943bddd08705a9"
+
# ProbeStar stuff
mkdir -p ProbeStar
cd ProbeStar
-for i in Cnomicon Cybersecurity KnowledgeBase linux_tools pi_tools Pynomicon Radio Robotics Software windows_tools
+rm -rf AutoSecurity CyberSecurity Database
+for i in Cnomicon Cybersecurity KnowledgeBase Pynomicon Radio Robotics Software git_tools linux_tools pi_tools windows_tools
do
echo "ProbeStar: $i"
if [ -d $i ]; then
rm -rf $i
fi
- git clone https://github.com/nprobert/$i
+ git clone https://github.com/nprobert/$i --recursive
cd ..
ln -fs ProbeStar/$i
cd ProbeStar
done
-rm -rf CyberSecurity Database
cd $HOME
+rm -f CyberSecurity Database CyVehicle
cp linux_tools/bin/* ~/bin
# NTCNA stuff
@@ -35,7 +40,7 @@ do
git clone https://github.com/nprobert/$i
done
cd $HOME
-for i in CInfrastructure CVehicle NissanV2X PyVehicle ProberN RosVehicle
+for i in CInfrastructure CVehicle PyVehicle RosVehicle
do
ln -fs NTCNA/$i $i
done
diff --git a/sbin/python-updates b/sbin/python-updates
index 1ed571c..e89f137 100755
--- a/sbin/python-updates
+++ b/sbin/python-updates
@@ -4,4 +4,4 @@
sudo -H pip3 install --upgrade pip
# Python3
-sudo -H pip3 install --upgrade pyserial numpy pyasn1 matplotlib pyside2 scapy virtualenv virtualenvwrapper
+sudo -H pip3 install --upgrade pyserial numpy pyasn1 scapy virtualenv virtualenvwrapper pyside2 matplotlib