Skip to content

Commit

Permalink
Merge branch 'bug/#1052urlRedirects'
Browse files Browse the repository at this point in the history
  • Loading branch information
spyhunter99 committed Jun 14, 2018
2 parents 1ad798f + ccc2bee commit f8fe850
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 24 deletions.
Expand Up @@ -59,6 +59,7 @@ public class DefaultConfigurationProvider implements IConfigurationProvider {
protected long mTileGCFrequencyInMillis = 300000;
protected int mTileGCBulkSize = 20;
protected long mTileGCBulkPauseInMillis = 500;
protected boolean mTileDownloaderFollowRedirects = true;

public DefaultConfigurationProvider(){

Expand Down Expand Up @@ -329,6 +330,7 @@ public void load(Context ctx, SharedPreferences prefs) {
setAnimationSpeedDefault(prefs.getInt("osmdroid.ZoomSpeedDefault", animationSpeedDefault));
setAnimationSpeedShort(prefs.getInt("osmdroid.animationSpeedShort", animationSpeedShort));
setCacheMapTileOvershoot((short)(prefs.getInt("osmdroid.cacheTileOvershoot", cacheTileOvershoot)));
setMapTileDownloaderFollowRedirects(prefs.getBoolean("osmdroid.TileDownloaderFollowRedirects", mTileDownloaderFollowRedirects));

if (prefs.contains("osmdroid.ExpirationOverride")) {
expirationOverride = prefs.getLong("osmdroid.ExpirationOverride",-1);
Expand Down Expand Up @@ -373,6 +375,7 @@ public void save(Context ctx, SharedPreferences prefs) {
edit.putBoolean("osmdroid.DebugMapView",isDebugMapView());
edit.putBoolean("osmdroid.DebugTileProvider",isDebugTileProviders());
edit.putBoolean("osmdroid.HardwareAcceleration", isMapViewHardwareAccelerated());
edit.putBoolean("osmdroid.TileDownloaderFollowRedirects", isMapTileDownloaderFollowRedirects());
edit.putString("osmdroid.userAgentValue", getUserAgentValue());
save(prefs, edit, mAdditionalHttpRequestProperties, "osmdroid.additionalHttpRequestProperty.");
edit.putLong("osmdroid.gpsWaitTime",gpsWaitTime);
Expand Down Expand Up @@ -532,4 +535,14 @@ public long getTileGCBulkPauseInMillis() {
public void setTileGCBulkPauseInMillis(final long pMillis) {
mTileGCBulkPauseInMillis = pMillis;
}

@Override
public void setMapTileDownloaderFollowRedirects(boolean value) {
mTileDownloaderFollowRedirects = value;
}

@Override
public boolean isMapTileDownloaderFollowRedirects() {
return mTileDownloaderFollowRedirects;
}
}
Expand Up @@ -426,4 +426,12 @@ public interface IConfigurationProvider {
* @since 6.0.2
*/
void setTileGCBulkPauseInMillis(final long pMillis);

/**
* enables/disables tile downloading following redirects. default is true
* @since 6.0.2
* @param value
*/
void setMapTileDownloaderFollowRedirects(boolean value);
boolean isMapTileDownloaderFollowRedirects();
}
Expand Up @@ -8,7 +8,6 @@
import org.osmdroid.config.Configuration;
import org.osmdroid.tileprovider.BitmapPool;
import org.osmdroid.tileprovider.MapTileRequestState;
import org.osmdroid.tileprovider.ReusableBitmapDrawable;
import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;
import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase.LowMemoryException;
import org.osmdroid.tileprovider.tilesource.ITileSource;
Expand Down Expand Up @@ -161,8 +160,20 @@ public void setTileSource(final ITileSource tileSource) {

protected class TileLoader extends MapTileModuleProviderBase.TileLoader {

@Override
public Drawable loadTile(final long pMapTileIndex) throws CantContinueException {

/**
* downloads a tile and follows http redirects
* @param pMapTileIndex
* @param redirectCount
* @param targetUrl
* @return
* @throws CantContinueException
*/
protected Drawable downloadTile(final long pMapTileIndex, final int redirectCount, final String targetUrl) throws CantContinueException {

//prevent infinite looping of redirects, rare but very possible for misconfigured servers
if (redirectCount>3)
return null;

OnlineTileSourceBase tileSource = mTileSource.get();
if (tileSource == null) {
Expand All @@ -172,18 +183,13 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
InputStream in = null;
OutputStream out = null;
HttpURLConnection c=null;

ByteArrayInputStream byteStream = null;
ByteArrayOutputStream dataStream = null;
try {

if (mNetworkAvailablityCheck != null
&& !mNetworkAvailablityCheck.getNetworkAvailable()) {
if (Configuration.getInstance().isDebugMode()) {
Log.d(IMapView.LOGTAG,"Skipping " + getName() + " due to NetworkAvailabliltyCheck.");
}
return null;
}

final String tileURLString = tileSource.getTileURLString(pMapTileIndex);

final String tileURLString = targetUrl;

if (Configuration.getInstance().isDebugMode()) {
Log.d(IMapView.LOGTAG,"Downloading Maptile from url: " + tileURLString);
Expand All @@ -193,6 +199,7 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
return null;
}

//TODO in the future, it may be necessary to allow app's using this library to override the SSL socket factory. It would here somewhere
if (Configuration.getInstance().getHttpProxy() != null) {
c = (HttpURLConnection) new URL(tileURLString).openConnection(Configuration.getInstance().getHttpProxy());
} else {
Expand All @@ -204,26 +211,66 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
c.setRequestProperty(entry.getKey(), entry.getValue());
}
c.connect();


// Check to see if we got success

if (c.getResponseCode() != 200) {
Log.w(IMapView.LOGTAG, "Problem downloading MapTile: " + MapTileIndex.toString(pMapTileIndex) + " HTTP response: " + c.getResponseMessage());
if (Configuration.getInstance().isDebugMapTileDownloader()) {
Log.d(IMapView.LOGTAG, tileURLString);


switch (c.getResponseCode()) {
case 301:
case 302:
case 307:
case 308:
if (Configuration.getInstance().isMapTileDownloaderFollowRedirects()) {
//this is a redirect, check the header for a 'Location' header
String redirectUrl = c.getHeaderField("Location");
if (redirectUrl != null) {
if (redirectUrl.startsWith("/")) {
//in this case we need to stitch together a full url
URL old = new URL(targetUrl);
int port = old.getPort();
boolean secure = targetUrl.toLowerCase().startsWith("https://");
if (port == -1)
if (targetUrl.toLowerCase().startsWith("http://")) {
port = 80;
} else {
port = 443;
}

redirectUrl = (secure ? "https://" : "http") + old.getHost() + ":" + port + redirectUrl;
}
Log.i(IMapView.LOGTAG, "Http redirect for MapTile: " + MapTileIndex.toString(pMapTileIndex) + " HTTP response: " + c.getResponseMessage() + " to url " + redirectUrl);
return downloadTile(pMapTileIndex, redirectCount + 1, redirectUrl);
}
break;
} //else follow through the normal path of aborting the download
default: {
Log.w(IMapView.LOGTAG, "Problem downloading MapTile: " + MapTileIndex.toString(pMapTileIndex) + " HTTP response: " + c.getResponseMessage());
if (Configuration.getInstance().isDebugMapTileDownloader()) {
Log.d(IMapView.LOGTAG, tileURLString);
}
Counters.tileDownloadErrors++;
in = c.getErrorStream(); // in order to have the error stream purged by the finally block
return null;
}
}
Counters.tileDownloadErrors++;
in = c.getErrorStream(); // in order to have the error stream purged by the finally block
return null;



}
String mime = c.getHeaderField("Content-Type");
if (Configuration.getInstance().isDebugMapTileDownloader()) {
Log.d(IMapView.LOGTAG, tileURLString + " success");
Log.d(IMapView.LOGTAG, tileURLString + " success, mime is " + mime );
}
if (mime!=null && !mime.toLowerCase().contains("image")) {
Log.w(IMapView.LOGTAG, tileURLString + " success, however the mime type does not appear to be an image " + mime );
}

in = c.getInputStream();

final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, StreamUtils.IO_BUFFER_SIZE);
//default is 1 week from now
//Date dateExpires;
Expand All @@ -247,7 +294,7 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
StreamUtils.copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
final ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
byteStream = new ByteArrayInputStream(data);

// Save the data to the cache
//this is the only point in which we insert tiles to the db or local file system.
Expand All @@ -258,6 +305,7 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
}
final Drawable result = tileSource.getDrawable(byteStream);


return result;
} catch (final UnknownHostException e) {
Log.w(IMapView.LOGTAG,"UnknownHostException downloading MapTile: " + MapTileIndex.toString(pMapTileIndex) + " : " + e);
Expand All @@ -279,6 +327,8 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
StreamUtils.closeStream(byteStream);
StreamUtils.closeStream(dataStream);
try{
c.disconnect();
} catch (Exception ex){}
Expand All @@ -287,6 +337,34 @@ public Drawable loadTile(final long pMapTileIndex) throws CantContinueException
return null;
}

@Override
public Drawable loadTile(final long pMapTileIndex) throws CantContinueException {

OnlineTileSourceBase tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}


if (mNetworkAvailablityCheck != null
&& !mNetworkAvailablityCheck.getNetworkAvailable()) {
if (Configuration.getInstance().isDebugMode()) {
Log.d(IMapView.LOGTAG, "Skipping " + getName() + " due to NetworkAvailabliltyCheck.");
}
return null;
}

final String tileURLString = tileSource.getTileURLString(pMapTileIndex);

if (TextUtils.isEmpty(tileURLString)) {
return null; //unlikely but just in case
}

return downloadTile(pMapTileIndex, 0, tileURLString);


}

@Override
protected void tileLoaded(final MapTileRequestState pState, final Drawable pDrawable) {
removeTileFromQueues(pState.getMapTile());
Expand Down

0 comments on commit f8fe850

Please sign in to comment.