+ remove deprecated components

This commit is contained in:
Reinhard Pointner 2014-08-06 12:03:16 +00:00
parent d7749f2eb1
commit e8749aa435
10 changed files with 75 additions and 396 deletions

View File

@ -69,19 +69,6 @@
<zipfileset src="${dir.dist}/filebot.jar" />
<!-- include libs -->
<zipfileset src="${dir.lib}/xercesMinimal.jar">
<include name="org/apache/**" />
<include name="org/w3c/dom/html/**" />
</zipfileset>
<zipfileset src="${dir.lib}/nekohtml.jar">
<include name="org/cyberneko/html/**" />
</zipfileset>
<zipfileset src="${dir.lib}/jsoup.jar">
<include name="org/jsoup/**" />
</zipfileset>
<zipfileset src="${dir.lib}/json-simple.jar">
<include name="org/json/simple/**" />
</zipfileset>
@ -90,10 +77,6 @@
<include name="com/cedarsoftware/util/**" />
</zipfileset>
<zipfileset src="${dir.lib}/simmetrics.jar">
<include name="uk/ac/shef/wit/simmetrics/**" />
</zipfileset>
<zipfileset src="${dir.lib}/glazedlists.jar">
<include name="ca/odell/glazedlists/**" />
</zipfileset>
@ -110,6 +93,10 @@
<include name="org/fife/**" />
</zipfileset>
<zipfileset src="${dir.lib}/simmetrics.jar">
<include name="uk/ac/shef/wit/simmetrics/**" />
</zipfileset>
<zipfileset src="${dir.lib}/xmlrpc.jar">
<include name="redstone/xmlrpc/**" />
</zipfileset>
@ -142,13 +129,14 @@
<include name="org/apache/commons/io/**" />
</zipfileset>
<!-- include classes and native libraries -->
<zipfileset src="${dir.lib}/jna.jar">
<include name="com/sun/jna/**" />
<zipfileset src="${dir.lib}/icu4j.jar">
<include name="com/ibm/icu/**" />
</zipfileset>
<zipfileset src="${dir.lib}/jna-platform.jar">
<include name="com/sun/jna/platform/win32/**" />
<zipfileset src="${dir.lib}/jacksum.jar">
<include name="jonelo/jacksum/adapt/**" />
<include name="jonelo/jacksum/algorithm/**" />
<include name="jonelo/sugar/util/**" />
</zipfileset>
<zipfileset src="${dir.lib}/groovy.jar">
@ -161,24 +149,6 @@
<exclude name="META-INF/services/org.codehaus.groovy.runtime.ExtensionModule" />
</zipfileset>
<zipfileset src="${dir.lib}/icu4j.jar">
<include name="com/ibm/icu/**" />
</zipfileset>
<zipfileset src="${dir.lib}/jacksum.jar">
<include name="jonelo/jacksum/adapt/**" />
<include name="jonelo/jacksum/algorithm/**" />
<include name="jonelo/sugar/util/**" />
</zipfileset>
<zipfileset src="${dir.lib}/junrar-custom.jar">
<include name="de/innosystec/unrar/**" />
</zipfileset>
<zipfileset src="${dir.lib}/jgat-custom.jar">
<include name="com/dmurph/tracking/**" />
</zipfileset>
<zipfileset src="${dir.lib}/sevenzipjbinding.jar">
<include name="net/sf/sevenzipjbinding/**" />
</zipfileset>
@ -188,6 +158,23 @@
<include name="com/sun/jna/**" />
</zipfileset>
<zipfileset src="${dir.lib}/jgat-custom.jar">
<include name="com/dmurph/tracking/**" />
</zipfileset>
<!-- include classes and native libraries -->
<zipfileset src="${dir.lib}/jna.jar">
<include name="com/sun/jna/**" />
</zipfileset>
<zipfileset src="${dir.lib}/jna-platform.jar">
<include name="com/sun/jna/platform/win32/**" />
</zipfileset>
<!-- libraries used in external scripts -->
<zipfileset src="${dir.lib}/jsoup.jar">
<include name="org/jsoup/**" />
</zipfileset>
<!-- Ivy for @Grapes automatic dependency management -->
<zipfileset src="${dir.lib}/scripting/ivy.jar">
<include name="org/apache/ivy/**" />

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +1,9 @@
package net.filebot.vfs;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.EnumSet;
public enum ArchiveType {
ZIP {
@ -17,19 +14,11 @@ public enum ArchiveType {
}
},
RAR {
@Override
public Iterable<MemoryFile> fromData(ByteBuffer data) {
return new RarArchive(data);
}
},
UNDEFINED {
@Override
public Iterable<MemoryFile> fromData(ByteBuffer data) {
for (ArchiveType type : EnumSet.of(ZIP, RAR)) {
for (ArchiveType type : EnumSet.of(ZIP)) {
try {
Iterable<MemoryFile> files = type.fromData(data);
if (files.iterator().hasNext()) {
@ -61,13 +50,9 @@ public enum ArchiveType {
if ("zip".equalsIgnoreCase(name))
return ZIP;
if ("rar".equalsIgnoreCase(name))
return RAR;
return UNKOWN;
}
public abstract Iterable<MemoryFile> fromData(ByteBuffer data);
}

View File

@ -1,75 +0,0 @@
package net.filebot.vfs;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.filebot.util.ByteBufferOutputStream;
import de.innosystec.unrar.Archive;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.rarfile.FileHeader;
public class RarArchive implements Iterable<MemoryFile> {
private final ByteBuffer data;
public RarArchive(ByteBuffer data) {
this.data = data.duplicate();
}
@Override
public Iterator<MemoryFile> iterator() {
try {
// extract rar archives one at a time, because of JUnRar memory problems
synchronized (RarArchive.class) {
return extract().iterator();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public List<MemoryFile> extract() throws IOException {
List<MemoryFile> vfs = new ArrayList<MemoryFile>();
try {
Archive rar = new Archive(data.duplicate());
for (FileHeader header : rar.getFileHeaders()) {
// ignore directory entries
if (header.isDirectory()) {
continue;
}
ByteBufferOutputStream buffer = new ByteBufferOutputStream(header.getDataSize());
try {
// write contents to buffer
rar.extractFile(header, buffer);
// add memory file
vfs.add(new MemoryFile(header.getFileNameString(), buffer.getByteBuffer()));
} catch (OutOfMemoryError e) {
// ignore, there seems to be bug with JUnRar allocating lots of memory for no apparent reason
// @see https://sourceforge.net/forum/forum.php?thread_id=2773018&forum_id=706772
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to extract " + header.getFileNameString(), e);
}
}
} catch (RarException e) {
throw new IOException(e);
}
return vfs;
}
}

View File

@ -26,8 +26,6 @@ import javax.swing.Icon;
import net.filebot.Cache;
import net.filebot.ResourceManager;
import org.json.simple.parser.ParseException;
import com.cedarsoftware.util.io.JsonObject;
import com.cedarsoftware.util.io.JsonReader;
@ -117,7 +115,7 @@ public class AcoustIDClient implements MusicIdentificationService {
return value == null ? null : new Integer(value.toString());
}
public AudioTrack parseResult(String json, final int targetDuration) throws IOException, InterruptedException, ParseException {
public AudioTrack parseResult(String json, final int targetDuration) throws IOException {
Map<?, ?> data = (Map<?, ?>) JsonReader.jsonToMaps(json);
if (!data.get("status").equals("ok")) {

View File

@ -1,160 +0,0 @@
package net.filebot.web;
import static net.filebot.util.XPathUtilities.*;
import static net.filebot.web.WebRequest.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.Icon;
import net.filebot.ResourceManager;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@Deprecated
public class IMDbClient implements MovieIdentificationService {
private String host = "www.imdb.com";
@Override
public String getName() {
return "IMDb";
}
@Override
public Icon getIcon() {
return ResourceManager.getIcon("search.imdb");
}
protected int getImdbId(String link) {
Matcher matcher = Pattern.compile("tt(\\d{7})").matcher(link);
if (matcher.find()) {
return Integer.parseInt(matcher.group(1));
}
// pattern not found
throw new IllegalArgumentException(String.format("Cannot find imdb id: %s", link));
}
@Override
public List<Movie> searchMovie(String query, Locale locale) throws Exception {
Document dom = parsePage(new URL("http", host, "/find?s=tt&q=" + encode(query, false)));
// select movie links followed by year in parenthesis
List<Node> nodes = selectNodes("//TABLE[@class='findList']//TD/A[substring-after(substring-before(following::text(),')'),'(')]", dom);
List<Movie> results = new ArrayList<Movie>(nodes.size());
for (Node node : nodes) {
try {
String name = node.getTextContent().trim();
if (name.startsWith("\""))
continue;
String year = node.getNextSibling().getTextContent().trim().replaceFirst("^\\(I\\)", "").replaceAll("[\\p{Punct}\\p{Space}]+", ""); // remove non-number characters
String href = getAttribute("href", node);
results.add(new Movie(name, Integer.parseInt(year), getImdbId(href), -1));
} catch (Exception e) {
// ignore illegal movies (TV Shows, Videos, Video Games, etc)
}
}
// we might have been redirected to the movie page
if (results.isEmpty()) {
try {
int imdbid = getImdbId(selectString("//LINK[@rel='canonical']/@href", dom));
Movie movie = getMovieDescriptor(imdbid, locale);
if (movie != null) {
results.add(movie);
}
} catch (Exception e) {
// ignore, can't find movie
}
}
return results;
}
protected Movie scrapeMovie(Document dom, Locale locale) {
try {
int imdbid = getImdbId(selectString("//LINK[@rel='canonical']/@href", dom));
String title = selectString("//META[@property='og:title']/@content", dom);
Matcher titleMatcher = Pattern.compile("(.+)\\s\\((?i:tv.|video.)?(\\d{4})\\)$").matcher(title);
if (!titleMatcher.matches())
return null;
return new Movie(titleMatcher.group(1), Integer.parseInt(titleMatcher.group(2)), imdbid, -1);
} catch (Exception e) {
// ignore, we probably got redirected to an error page
return null;
}
}
@Override
public Movie getMovieDescriptor(int imdbid, Locale locale) throws Exception {
if (imdbid <= 0) {
throw new IllegalArgumentException("id must not be " + imdbid);
}
try {
return scrapeMovie(parsePage(new URL("http", host, String.format("/title/tt%07d/", imdbid))), locale);
} catch (FileNotFoundException e) {
return null; // illegal imdbid
}
}
protected Document parsePage(URL url) throws IOException, SAXException {
CachedPage page = new CachedPage(url) {
@Override
protected Reader openConnection(URL url) throws IOException {
URLConnection connection = url.openConnection();
// IMDb refuses default user agent (Java/1.6.0_12) => SPOOF GOOGLEBOT
connection.addRequestProperty("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)");
connection.addRequestProperty("From", "googlebot(at)googlebot.com");
connection.addRequestProperty("Accept", "*/*");
connection.addRequestProperty("X-Forwarded-For", "66.249.73.100"); // TRICK ANNOYING IMDB GEO-LOCATION LOCALIZATION
return getReader(connection);
}
};
return getHtmlDocument(page.get());
}
public String scrape(String imdbid, String xpath) throws IOException, SAXException {
return scrape(getMoviePageLink(getImdbId(imdbid)).toURL(), xpath); // helper for scraping data in user scripts
}
public String scrape(URL url, String xpath) throws IOException, SAXException {
return selectString(xpath, parsePage(url)); // helper for scraping data in user scripts
}
public URI getMoviePageLink(int imdbId) {
return URI.create(String.format("http://www.imdb.com/title/tt%07d/", imdbId));
}
@Override
public Map<File, Movie> getMovieDescriptors(Collection<File> movieFiles, Locale locale) throws Exception {
throw new UnsupportedOperationException();
}
}

View File

@ -14,9 +14,6 @@ import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -29,30 +26,17 @@ import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.filebot.util.ByteBufferOutputStream;
import org.cyberneko.html.parsers.DOMParser;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public final class WebRequest {
public static Document getHtmlDocument(URL url) throws IOException, SAXException {
return getHtmlDocument(url.openConnection());
}
public static Document getHtmlDocument(URLConnection connection) throws IOException, SAXException {
return getHtmlDocument(getReader(connection));
}
public static Reader getReader(URLConnection connection) throws IOException {
try {
connection.addRequestProperty("Accept-Encoding", "gzip,deflate");
@ -75,18 +59,6 @@ public final class WebRequest {
return new InputStreamReader(inputStream, charset);
}
public static Document getHtmlDocument(Reader reader) throws SAXException, IOException {
DOMParser parser = new DOMParser();
parser.setFeature("http://xml.org/sax/features/namespaces", false);
parser.parse(new InputSource(reader));
return parser.getDocument();
}
public static Document getHtmlDocument(String html) throws SAXException, IOException {
return getHtmlDocument(new StringReader(html));
}
public static Document getDocument(URL url) throws IOException, SAXException {
return getDocument(url.openConnection());
}
@ -236,6 +208,40 @@ public final class WebRequest {
return c.getResponseCode();
}
public static String encodeParameters(Map<String, ?> parameters, boolean unicode) {
StringBuilder sb = new StringBuilder();
for (Entry<String, ?> entry : parameters.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(entry.getKey());
if (entry.getValue() != null) {
sb.append("=");
sb.append(encode(entry.getValue().toString(), unicode));
}
}
return sb.toString();
}
private static byte[] gzip(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(data);
gzip.close();
return out.toByteArray();
}
public static String encode(String string, boolean unicode) {
try {
return URLEncoder.encode(string, unicode ? "UTF-8" : "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static Charset getCharset(String contentType) {
if (contentType != null) {
// e.g. Content-Type: text/html; charset=iso-8859-1
@ -259,67 +265,6 @@ public final class WebRequest {
return Charset.forName("UTF-8");
}
public static String encodeParameters(Map<String, ?> parameters, boolean unicode) {
StringBuilder sb = new StringBuilder();
for (Entry<String, ?> entry : parameters.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(entry.getKey());
if (entry.getValue() != null) {
sb.append("=");
sb.append(encode(entry.getValue().toString(), unicode));
}
}
return sb.toString();
}
public static String encode(String string, boolean unicode) {
try {
return URLEncoder.encode(string, unicode ? "UTF-8" : "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static byte[] gzip(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(data);
gzip.close();
return out.toByteArray();
}
public static SSLSocketFactory createIgnoreCertificateSocketFactory() {
// create a trust manager that does not validate certificate chains
TrustManager trustAnyCertificate = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
};
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { trustAnyCertificate }, new SecureRandom());
return sc.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
/**
* Dummy constructor to prevent instantiation.
*/

View File

@ -6,7 +6,6 @@ import java.io.IOException;
import net.sf.ehcache.CacheManager;
import org.json.simple.parser.ParseException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@ -28,7 +27,7 @@ public class AcoustIDClientTest {
}
@Test
public void lookupChinese() throws IOException, InterruptedException, ParseException {
public void lookupChinese() throws IOException, InterruptedException {
int duration = 265;
String fingerprint = "AQADtJmWRFJCRkGcHXceND_Oquhz1H_xvjg8D8mYIf5-fOpKVE81NOOF5_hb1PrxJLhhRxfCLkNSOh-61Mvh3DJKOcMnG2eOPsmH_4R_I-SPJB-Df0NTB70-vPiDRtKOS3qK-Duhc8mR9-jyoOvhKhyJH-8FE5eOHHoy3BpC5Tieo_kV9LiZ41McHCF9iJmDPFTQPeiYHD5J_Cfy7DBz_IdxrXBRMTyeP9CSLeJQ8glyC18S5imeSHkSPBeavwgfHrqSD7l09Fl2mGMDVzmekAzS_Gi3HPJbIr0VvD2eJD8u-eAPxytyMccTTQ8u5YmR63iG5jm6UG3wJcmFyzFuNEclvcETfcSb4T-aDz0RWoGs5MQlg9mUBXlyodYjbId_lHke4vPxCFuO5-iNJkw-5FseJM9RckFPHJ-kH3USNL_w4i7xpT5iHvlCVOIR5viFJyFK2Yd59DzqHe8wNUfJF1rwakJTZdB_TJkk5Ntx6YOb7MHj40SZh1ERZv3wD3yaohmzC-2DyM_xND_e48-CWx-6H5FC6ApxpUf-4jpyuEo64VLCZsrwHXcWlBcaDdeWI6Zz5D9qQ0wz4WNPPPCYWWgv6OTw7Ugb_Ghihkd4gdKSqBL0hGyCH1q59GjkHaeQJ0fJLEbz2XiOmBu-RIemG55TDmGPJ3i04zouycIZuMrI4Exz480xqvnxhUS68oHKTD7-I1LGLEX7CteFmNGDD3qO6UvQRNSxKsoVXDnurEHzYWIfPKmFWJqJp3OQP4c5Ukqhx0QeY_-OXj1MLozw6AzqJBmOfNCUKslDhOHB40mGR19wHT0RplRwMsQT5VGG_Kh--D2qKEpU4quFc0Z5NIx4fJIXnHjR73COkNCaJEdF0cifE2SkPHiEJj76Y8qzHO27FE-O79hyS8R59HoQRssV6NKRx6i-o2eKP0ednGiq4Ej1oHeGZgqJnzOeCyEzvmh0XCryaLlRSUJ6YjpxHdd04-qE_kVz_EGNOsR84cuFMJNooWIgNzziKw2anUeZ5cYzBbyI3jnCPB90R0L0hFSBJxfmLLPQHF2T4Ql5nD2eWMFtwnWQL8msQF-MfEezC0x34wue48kRktORUIcbB-fhZw-87ArKI8-E5AmD-mieB7dyXKQYXMvxHDkU5T9K8sTTQ1eLPkeYG992xAweQ-eD5lmDUN_xicaX6PiNM1vxw91InGmOv7ior_AXPDueXbiOhlwkHeUV_DF-5D90Fc1zJCMzK8aT45KNV0XzYvJxJccfIZ-RLEdPKcGzDkdPonmWDMcf4WFy_MGTFVoiGp3WRwOfZMd1PDnxJ4GbCc9O5Eeih2jWo2_AKpPxKMTFHVWOhEdo_AmuD89yNJETdEdSHmGcHEezrjFoCZf0w8Lo7PC54M6DT-vwhEcPP4Hzo9uOH98TJH_TIRJzHNaS4-TBz8nRh8GZFz-eG08f9MzRrDu-iMjWC5eG_wjpoQl_zNHx3mh6BT09o1Zg93iKZj0uhSQmH8nyBHl3VHszUM9RytLwJEqKmT96NC-H41eIHzk0PUeYSx_WCE9y4qaGo7KUomk0C9eJ5L-RfUFzodSLJ3goHX3gHHkJPUMuFdfyJHB8hCeSZxH4BE1vVL6CrkmM6lEePGeK_Ei0v8KTw9GRb3gO_YfjLMgn6agYIh3xfIJ2T8jDodR2OAyso8e3bIrhJgyHHzvyKhCjpxE-MUIezeiD5suW4LzxJEfMlEJy4VFCNNeLUjqeJJ6OP8PNwsfTB9dxHUmeXAgzLuHQ4wljfDqahegj4R2JKzlO5fiDkuERJkfiKVHwxB_OHPyH6soEJk07fB9u6CyF5rmCflFwBdyiRHg4IReSBfWDX8GnHGVGNHOE-NCssEjTHFeNplsPdgmqKBea8eiD5jwuBo-SZ6gkfmhk4U6EpmKOPviJUD-S50WVgE911Id9HX3k4AmHG-9fPAneJ-hBjcWjoPzxHI9JhDSx5awQSlGPWg_8bULPHE2VE30oNNNQb7hyTD4aVUYeQUv2Ivzw1AEd7Wge9Ph-4M_xC89uJEusIVyY4cWTRC_-4-hNNI2WSciP5J3BL_Au4UyPKzgaPUN4yAuP0Dw85jqejE6CUNCRZ8OTo-mD58atGJ0jXjjjIxd09gh7hNnx4UkOnYe_4MQDTWJgaauE8Bc-KmgTDQ_6CleKD6Z8Yufxtwh1QcuCfEmGS4rwE_444TniREmOH-_wCP6MO2mDNUouPNEPTUfzqMPZI1_EB1feHDeFkjzCjMygJznuI2dYouXhS3gfhOXxi9Ap2Uj14DyeJFl6sHrwH37wKRm-8HiUJwnOC-UTNFJ1XMwz4eKDr0GbH54kVJWC78GpVfjRHD2SLcmGb0f44SAj5WgfNGOO5j36K_jUo09mNMWDbrbQOEcsLSeS50fPHL9QUceFKhOP4w_cGKGV489FPD0aJTvKP_hE6EmGpkKZH7ri4FRm44o5oZQ5-Jh-ou_RNImCw1GqTYjMo_aDRsuO__gS-CKefQlyKSf4NEdPGmGOP8eZKbjihzh1nJ_QvEa4Q6VC4UqkIz_-oEeYUH3wRR--C10JD7WOMwquhwbPQ9t6Iw1TXMNPnBciZXkC1YiYRSxq-MI35KikzEoCpcrxLNB2NDlyKcPIGH0OH3eE5wglrdB3hOGH6eKEMw725Oh39DN-NP1RMaGHhznu7Ei_ZIWei7iSCnmOZvbQM1zQ78hTo-aA6ROhJWKi49OxJzdi9fgUlL_RNMm644suXEcsJjua69BsfFpKPDrCV4fPIFe-4IknofKNo9O0Q9L4oFauoBzaiD7eG018oZSj44nW4HlCNPFioa2CPMyFUzye5vjR7mgibTitiRh5Yj7aCQAIMEQoACCQQABhCBNGCMGUEcAYYg1AQCAhDDAAAAagAQAQAAh0BmBCiPAMEHOUAAogASCBBAAklFBEEWaEIkQAAAQjQAgAgHHCIASIA0gQQwQASBggBBFKUCMAIFQSBIQERAnCECRWEACEQJIipYABnIEhACECEUAIs8wg4QRCACBmBCAEKAEIAwYpABSACAAECASCCEKgE04oYBRQChgHhABkAUEAEAIwAwAgQFAgFGMUGcIoA0AIARgAyBhAFKIKCEOIAgQZIARARhgggBGUAYiRAUAIRYQEBABAkBAECOMMIgAIhIQBCiCFCHBMEASAAEoACogoCAFGgGUGWIUAMIgRBIAzhgAFFAJEAEIEgAwZoBgAmCFmhKEMGAAUAAYsQgABgChgNAUGAASIgEAYB4gRQABBBGMGCKEAAIwggShwCChkgGIEGQaocoQBoLRBSACOHALEMQAEAkwAYoAkTDkDICEKIUMQAEQEQRRAgBCJACJCIWSAAKwBQYQABEkCBRHAAEUAoAJIgYBQTAkDAAEIIGEEMIsQx4wAwhgiEQFCGAQQA0oY4gUhCgElgEHEOECEUAYhJAQwxBgJJANIUQKEIYIoARgDhhlAHFBIIAmQQRYhoAhhCBgnLCKEKCEQIQEIR4RTCgkkCAKGCmQQQQAQgAQFgBFBCCGSAwAEIcoIoJQEDCHhEDAKKmCREswQohAgiglkACACKgOhMUAhRgwCBAipEFGMAAGEUABYhAhSAiEFoFEQASGAIAAxJQiESDEHgCEISAEQEAAIJwhAShGoBAUAUCaIUAwIgQgzghgggECAKCIcMQoJxYgSwABlhACAMgMAEkwCpCBzhgADGDACWMIEA0YbIQBiQAAgGCFAKCCEJBAAAYwhAGmiCCOOAIEcMwAIggBzjBhHmHeMSCGIEggiAA0jTCHjCABCAAUQIUQJIowQggFkKBEAGCEBBMQgBIARBkGDCCFGCMMMIIAgQBgSSAI";