use of com.biglybt.core.torrent.TOTorrentException in project BiglyBT by BiglySoftware.
the class TOTorrentDeserialiseImpl method construct.
protected void construct(Map meta_data) throws TOTorrentException {
try {
String announce_url = null;
boolean got_announce = false;
boolean got_announce_list = false;
boolean bad_announce = false;
// decode the stuff
Iterator root_it = meta_data.keySet().iterator();
while (root_it.hasNext()) {
String key = (String) root_it.next();
if (key.equalsIgnoreCase(TK_ANNOUNCE)) {
got_announce = true;
announce_url = readStringFromMetaData(meta_data, TK_ANNOUNCE);
if (announce_url == null || announce_url.trim().length() == 0) {
bad_announce = true;
} else {
announce_url = announce_url.replaceAll(" ", "");
try {
setAnnounceURL(new URL(announce_url));
} catch (MalformedURLException e) {
if (!announce_url.contains("://")) {
announce_url = "http:/" + (announce_url.startsWith("/") ? "" : "/") + announce_url;
} else if (announce_url.startsWith("utp:")) {
// common typo for udp
announce_url = "udp" + announce_url.substring(3);
}
try {
setAnnounceURL(new URL(announce_url));
} catch (MalformedURLException f) {
Debug.out("Invalid announce url: " + announce_url);
bad_announce = true;
}
}
}
} else if (key.equalsIgnoreCase(TK_ANNOUNCE_LIST)) {
got_announce_list = true;
List announce_list = null;
Object ann_list = meta_data.get(TK_ANNOUNCE_LIST);
if (ann_list instanceof List) {
// some malformed torrents have this key as a zero-sized string instead of a zero-sized list
announce_list = (List) ann_list;
}
if (announce_list != null && announce_list.size() > 0) {
announce_url = readStringFromMetaData(meta_data, TK_ANNOUNCE);
if (announce_url != null) {
announce_url = announce_url.replaceAll(" ", "");
}
boolean announce_url_found = false;
for (int i = 0; i < announce_list.size(); i++) {
Object temp = announce_list.get(i);
if (temp instanceof byte[]) {
List l = new ArrayList();
l.add(temp);
temp = l;
}
if (temp instanceof List) {
Vector urls = new Vector();
List set = (List) temp;
while (set.size() > 0) {
// seen a case where this is a list with the announce url first and then some other junk
Object temp2 = set.remove(0);
try {
if (temp2 instanceof List) {
List junk = (List) temp2;
if (junk.size() > 0) {
set.add(junk.get(0));
}
continue;
}
String url_str = readStringFromMetaData((byte[]) temp2);
url_str = url_str.replaceAll(" ", "");
try {
urls.add(new URL(StringInterner.intern(url_str)));
if (url_str.equalsIgnoreCase(announce_url)) {
announce_url_found = true;
}
} catch (MalformedURLException e) {
if (!url_str.contains("://")) {
url_str = "http:/" + (url_str.startsWith("/") ? "" : "/") + url_str;
} else if (url_str.startsWith("utp:")) {
// common typo
url_str = "udp" + url_str.substring(3);
}
try {
urls.add(new URL(StringInterner.intern(url_str)));
if (url_str.equalsIgnoreCase(announce_url)) {
announce_url_found = true;
}
} catch (MalformedURLException f) {
Debug.out("Invalid url: " + url_str, f);
}
}
} catch (Throwable e) {
Debug.out("Torrent has invalid url-list entry (" + temp2 + ") - ignoring: meta=" + meta_data, e);
}
}
if (urls.size() > 0) {
URL[] url_array = new URL[urls.size()];
urls.copyInto(url_array);
addTorrentAnnounceURLSet(url_array);
}
} else {
Debug.out("Torrent has invalid url-list entry (" + temp + ") - ignoring: meta=" + meta_data);
}
}
if (!announce_url_found && announce_url != null && announce_url.length() > 0) {
try {
Vector urls = new Vector();
urls.add(new URL(StringInterner.intern(announce_url)));
URL[] url_array = new URL[urls.size()];
urls.copyInto(url_array);
addTorrentAnnounceURLSet(url_array);
} catch (Exception e) {
Debug.out("Invalid URL '" + announce_url + "' - meta=" + meta_data, e);
}
}
}
} else if (key.equalsIgnoreCase(TK_COMMENT)) {
setComment((byte[]) meta_data.get(TK_COMMENT));
} else if (key.equalsIgnoreCase(TK_CREATED_BY)) {
setCreatedBy((byte[]) meta_data.get(TK_CREATED_BY));
} else if (key.equalsIgnoreCase(TK_CREATION_DATE)) {
try {
Long creation_date = (Long) meta_data.get(TK_CREATION_DATE);
if (creation_date != null) {
setCreationDate(creation_date.longValue());
}
} catch (Exception e) {
System.out.println("creation_date extraction fails, ignoring");
}
} else if (key.equalsIgnoreCase(TK_INFO)) {
// processed later
} else {
Object prop = meta_data.get(key);
if (prop instanceof byte[]) {
setAdditionalByteArrayProperty(key, (byte[]) prop);
} else if (prop instanceof Long) {
setAdditionalLongProperty(key, (Long) prop);
} else if (prop instanceof List) {
setAdditionalListProperty(key, (List) prop);
} else {
setAdditionalMapProperty(key, (Map) prop);
}
}
}
if (bad_announce) {
if (got_announce_list) {
TOTorrentAnnounceURLSet[] sets = getAnnounceURLGroup().getAnnounceURLSets();
if (sets.length > 0) {
setAnnounceURL(sets[0].getAnnounceURLs()[0]);
} else {
throw (new TOTorrentException("ANNOUNCE_URL malformed ('" + announce_url + "' and no usable announce list)", TOTorrentException.RT_DECODE_FAILS));
}
} else {
throw (new TOTorrentException("ANNOUNCE_URL malformed ('" + announce_url + "'", TOTorrentException.RT_DECODE_FAILS));
}
}
if (!(got_announce_list || got_announce)) {
setAnnounceURL(TorrentUtils.getDecentralisedEmptyURL());
}
if (getAnnounceURL() == null) {
boolean done = false;
if (got_announce_list) {
TOTorrentAnnounceURLSet[] sets = getAnnounceURLGroup().getAnnounceURLSets();
if (sets.length > 0) {
setAnnounceURL(sets[0].getAnnounceURLs()[0]);
done = true;
}
}
if (!done) {
setAnnounceURL(TorrentUtils.getDecentralisedEmptyURL());
}
}
Map info = (Map) meta_data.get(TK_INFO);
if (info == null) {
throw (new TOTorrentException("Decode fails, 'info' element not found'", TOTorrentException.RT_DECODE_FAILS));
}
boolean hasUTF8Keys = info.containsKey(TK_NAME_UTF8);
setName((byte[]) info.get(TK_NAME));
long piece_length = ((Long) info.get(TK_PIECE_LENGTH)).longValue();
if (piece_length <= 0) {
throw (new TOTorrentException("Decode fails, piece-length is invalid", TOTorrentException.RT_DECODE_FAILS));
}
setPieceLength(piece_length);
setHashFromInfo(info);
Long simple_file_length = (Long) info.get(TK_LENGTH);
long total_length = 0;
String encoding = getAdditionalStringProperty("encoding");
hasUTF8Keys &= encoding == null || encoding.equals(ENCODING_ACTUALLY_UTF8_KEYS);
if (simple_file_length != null) {
setSimpleTorrent(true);
total_length = simple_file_length.longValue();
if (hasUTF8Keys) {
setNameUTF8((byte[]) info.get(TK_NAME_UTF8));
setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS);
}
setFiles(new TOTorrentFileImpl[] { new TOTorrentFileImpl(this, 0, 0, total_length, new byte[][] { getName() }) });
} else {
setSimpleTorrent(false);
List meta_files = (List) info.get(TK_FILES);
TOTorrentFileImpl[] files = new TOTorrentFileImpl[meta_files.size()];
if (hasUTF8Keys) {
for (int i = 0; i < files.length; i++) {
Map file_map = (Map) meta_files.get(i);
hasUTF8Keys &= file_map.containsKey(TK_PATH_UTF8);
if (!hasUTF8Keys) {
break;
}
}
if (hasUTF8Keys) {
setNameUTF8((byte[]) info.get(TK_NAME_UTF8));
setAdditionalStringProperty("encoding", ENCODING_ACTUALLY_UTF8_KEYS);
}
}
for (int i = 0; i < files.length; i++) {
Map file_map = (Map) meta_files.get(i);
long len = ((Long) file_map.get(TK_LENGTH)).longValue();
List paths = (List) file_map.get(TK_PATH);
List paths8 = (List) file_map.get(TK_PATH_UTF8);
byte[][] path_comps = null;
if (paths != null) {
path_comps = new byte[paths.size()][];
for (int j = 0; j < paths.size(); j++) {
path_comps[j] = (byte[]) paths.get(j);
}
}
TOTorrentFileImpl file;
if (hasUTF8Keys) {
byte[][] path_comps8 = new byte[paths8.size()][];
for (int j = 0; j < paths8.size(); j++) {
path_comps8[j] = (byte[]) paths8.get(j);
}
file = files[i] = new TOTorrentFileImpl(this, i, total_length, len, path_comps, path_comps8);
} else {
file = files[i] = new TOTorrentFileImpl(this, i, total_length, len, path_comps);
}
total_length += len;
// preserve any non-standard attributes
Iterator file_it = file_map.keySet().iterator();
while (file_it.hasNext()) {
String key = (String) file_it.next();
if (key.equals(TK_LENGTH) || key.equals(TK_PATH)) {
// standard
// we don't skip TK_PATH_UTF8 because some code might assume getAdditionalProperty can get it
} else {
file.setAdditionalProperty(key, file_map.get(key));
}
}
}
setFiles(files);
}
byte[] flat_pieces = (byte[]) info.get(TK_PIECES);
// work out how many pieces we require for the torrent
int pieces_required = (int) ((total_length + (piece_length - 1)) / piece_length);
int pieces_supplied = flat_pieces.length / 20;
if (pieces_supplied < pieces_required) {
throw (new TOTorrentException("Decode fails, insufficient pieces supplied", TOTorrentException.RT_DECODE_FAILS));
}
if (pieces_supplied > pieces_required) {
Debug.out("Torrent '" + new String(getName()) + "' has too many pieces (required=" + pieces_required + ",supplied=" + pieces_supplied + ") - ignoring excess");
}
byte[][] pieces = new byte[pieces_supplied][20];
for (int i = 0; i < pieces.length; i++) {
System.arraycopy(flat_pieces, i * 20, pieces[i], 0, 20);
}
setPieces(pieces);
// extract and additional info elements
Iterator info_it = info.keySet().iterator();
while (info_it.hasNext()) {
String key = (String) info_it.next();
if (key.equals(TK_NAME) || key.equals(TK_LENGTH) || key.equals(TK_FILES) || key.equals(TK_PIECE_LENGTH) || key.equals(TK_PIECES)) {
// standard attributes
} else {
addAdditionalInfoProperty(key, info.get(key));
}
}
try {
byte[] ho = (byte[]) info.get(TK_HASH_OVERRIDE);
if (ho != null) {
setHashOverride(ho);
} else {
if (info instanceof LightHashMapEx) {
LightHashMapEx info_ex = (LightHashMapEx) info;
if (info_ex.getFlag(LightHashMapEx.FL_MAP_ORDER_INCORRECT)) {
String name = getUTF8Name();
if (name == null) {
name = new String(getName());
}
String message = MessageText.getString("torrent.decode.info.order.bad", new String[] { name });
LogAlert alert = new LogAlert(this, LogAlert.UNREPEATABLE, LogAlert.AT_WARNING, message);
alert.forceNotify = true;
Logger.log(alert);
}
}
}
} catch (Throwable e) {
Debug.printStackTrace(e);
}
} catch (Throwable e) {
if (e instanceof TOTorrentException) {
throw ((TOTorrentException) e);
}
throw (new TOTorrentException("Torrent decode fails '" + Debug.getNestedExceptionMessageAndStack(e) + "'", TOTorrentException.RT_DECODE_FAILS, e));
}
}
use of com.biglybt.core.torrent.TOTorrentException in project BiglyBT by BiglySoftware.
the class TOTorrentXMLDeserialiser method readGenericMapEntry.
protected mapEntry readGenericMapEntry(SimpleXMLParserDocumentNode node) throws TOTorrentException {
if (!node.getName().equalsIgnoreCase("KEY")) {
throw (new TOTorrentException("Additional property invalid, must be KEY node", TOTorrentException.RT_DECODE_FAILS));
}
String name = node.getAttribute("name").getValue();
SimpleXMLParserDocumentNode[] kids = node.getChildren();
if (kids.length != 1) {
throw (new TOTorrentException("Additional property invalid, KEY must have one child", TOTorrentException.RT_DECODE_FAILS));
}
String type = kids[0].getName();
Object value = readGenericValue(kids[0]);
return (new mapEntry(name, value));
}
use of com.biglybt.core.torrent.TOTorrentException in project BiglyBT by BiglySoftware.
the class SubscriptionSchedulerImpl method download.
@Override
public void download(final Subscription subs, final SubscriptionResult original_result) {
String download_link = original_result.getDownloadLink();
if (download_link == null) {
log(subs.getName() + ": can't download " + original_result.getID() + " as no direct download link available");
return;
}
final String key = subs.getID() + ":" + original_result.getID();
final String dl = download_link;
synchronized (active_result_downloaders) {
if (active_result_downloaders.contains(key)) {
return;
}
log(subs.getName() + ": queued result for download - " + original_result.getID() + "/" + download_link);
active_result_downloaders.add(key);
result_downloader.run(new AERunnable() {
@Override
public void runSupport() {
// need to fix up to the latest history due to the lazy nature of things :(
SubscriptionResult result = subs.getHistory().getResult(original_result.getID());
boolean success = false;
try {
if (result == null) {
log(subs.getName() + ": result has been deleted - " + original_result.getID());
success = true;
} else if (result.getRead()) {
log(subs.getName() + ": result already marked as read, skipping - " + result.getID());
success = true;
} else {
boolean retry = true;
boolean use_ref = subs.getHistory().getDownloadWithReferer();
boolean tried_ref_switch = false;
while (retry) {
retry = false;
try {
TorrentUtils.setTLSDescription("Subscription: " + subs.getName());
URL original_url = new URL(dl);
PluginProxy plugin_proxy = null;
if (dl.startsWith("tor:")) {
String target_resource = dl.substring(4);
original_url = new URL(target_resource);
Map<String, Object> options = new HashMap<>();
options.put(AEProxyFactory.PO_PEER_NETWORKS, new String[] { AENetworkClassifier.AT_TOR });
plugin_proxy = AEProxyFactory.getPluginProxy("Subscription result download of '" + target_resource + "'", original_url, options, true);
if (plugin_proxy == null) {
throw (new Exception("No Tor plugin proxy available for '" + dl + "'"));
}
}
URL current_url = plugin_proxy == null ? original_url : plugin_proxy.getURL();
Torrent torrent = null;
try {
while (true) {
try {
ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
ResourceDownloader url_rd = rdf.create(current_url, plugin_proxy == null ? null : plugin_proxy.getProxy());
if (plugin_proxy != null) {
url_rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (current_url.getPort() == -1 ? "" : (":" + current_url.getPort())));
}
String referer = use_ref ? subs.getReferer() : null;
UrlUtils.setBrowserHeaders(url_rd, referer);
Engine engine = subs.getEngine();
if (engine instanceof WebEngine) {
WebEngine we = (WebEngine) engine;
if (we.isNeedsAuth()) {
String cookies = we.getCookies();
if (cookies != null && cookies.length() > 0) {
url_rd.setProperty("URL_Cookie", cookies);
}
}
}
ResourceDownloader mr_rd = rdf.getMetaRefreshDownloader(url_rd);
InputStream is = mr_rd.download();
torrent = new TorrentImpl(TOTorrentFactory.deserialiseFromBEncodedInputStream(is));
break;
} catch (Throwable e) {
if (plugin_proxy == null) {
plugin_proxy = AEProxyFactory.getPluginProxy("Subscription result download", original_url);
if (plugin_proxy != null) {
current_url = plugin_proxy.getURL();
continue;
}
}
throw (e);
}
}
} finally {
if (plugin_proxy != null) {
plugin_proxy.setOK(torrent != null);
}
}
byte[] hash = torrent.getHash();
// PlatformTorrentUtils.setContentTitle(torrent, torr );
DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager();
Download download;
// if we're assigning a tag/networks then we need to add it stopped in case the tag has any pre-start actions (e.g. set initial save location)
// this is because the assignments are done in SubscriptionManagerImpl on the download(willbe)added event
boolean stop_override = subs.getTagID() >= 0 || subs.getHistory().getDownloadNetworks() != null;
boolean auto_start = manager.shouldAutoStart(torrent);
manager.addPrepareTrigger(hash, new Subscription[] { subs }, new SubscriptionResult[] { result });
try {
if (auto_start && !stop_override) {
download = dm.addDownload(torrent);
} else {
download = dm.addDownloadStopped(torrent, null, null);
}
} finally {
manager.removePrepareTrigger(hash);
}
log(subs.getName() + ": added download " + download.getName() + ": auto-start=" + auto_start);
// maybe remove this as should be actioned in the trigger?
manager.prepareDownload(download, new Subscription[] { subs }, new SubscriptionResult[] { result });
subs.addAssociation(hash);
if (auto_start && stop_override) {
download.restart();
}
result.setRead(true);
success = true;
if (tried_ref_switch) {
subs.getHistory().setDownloadWithReferer(use_ref);
}
} catch (Throwable e) {
log(subs.getName() + ": Failed to download result " + dl, e);
if (e instanceof TOTorrentException && !tried_ref_switch) {
use_ref = !use_ref;
tried_ref_switch = true;
retry = true;
log(subs.getName() + ": Retrying " + (use_ref ? "with referer" : "without referer"));
}
} finally {
TorrentUtils.setTLSDescription(null);
}
}
}
} finally {
try {
if (!success) {
if (dl.startsWith("azplug:") || dl.startsWith("chat:")) {
// whatever the outcome these have been handled async
result.setRead(true);
} else {
int rad = manager.getAutoDownloadMarkReadAfterDays();
if (rad > 0) {
long rad_millis = rad * 24 * 60 * 60 * 1000L;
long time_found = result.getTimeFound();
if (time_found > 0 && time_found + rad_millis < SystemTime.getCurrentTime()) {
log(subs.getName() + ": result expired, marking as read - " + result.getID());
result.setRead(true);
}
}
}
}
} catch (Throwable e) {
Debug.out(e);
}
synchronized (active_result_downloaders) {
active_result_downloaders.remove(key);
}
calculateSchedule();
}
}
});
}
}
use of com.biglybt.core.torrent.TOTorrentException in project BiglyBT by BiglySoftware.
the class TrackerChecker method peekHashData.
protected TRTrackerScraperResponseImpl peekHashData(TOTorrent torrent, URL target_url) {
try {
URL trackerUrl = target_url == null ? torrent.getAnnounceURL() : target_url;
if (trackerUrl == null) {
return (null);
}
String url_str = trackerUrl.toString();
try {
trackers_mon.enter();
TrackerStatus ts = (TrackerStatus) trackers.get(url_str);
if (ts != null) {
return (ts.getHashData(torrent.getHashWrapper()));
}
} finally {
trackers_mon.exit();
}
} catch (TOTorrentException e) {
Debug.printStackTrace(e);
}
return null;
}
use of com.biglybt.core.torrent.TOTorrentException in project BiglyBT by BiglySoftware.
the class TRHostImpl method remove.
protected void remove(TRHostTorrent host_torrent) {
try {
this_mon.enter();
if (!host_torrents.contains(host_torrent)) {
return;
}
host_torrents.remove(host_torrent);
TOTorrent torrent = host_torrent.getTorrent();
try {
host_torrent_hash_map.remove(new HashWrapper(torrent.getHash()));
} catch (TOTorrentException e) {
Debug.printStackTrace(e);
}
host_torrent_map.remove(torrent);
if (host_torrent instanceof TRHostTorrentHostImpl) {
stopHosting((TRHostTorrentHostImpl) host_torrent);
}
listeners.dispatch(LDT_TORRENT_REMOVED, host_torrent);
// this'll get saved sometime soon anyway - performance problems
// here when removing multiple torrents from a large set (e.g. 1000)
// config.saveConfig();
} finally {
this_mon.exit();
}
}
Aggregations