mirror of
https://gitlab.com/oeffi/oeffi.git
synced 2025-07-06 17:38:48 +00:00
StationDetailsActivity, DecodeForeignActivity: remove deep links from QR codes and NDEF messages
Android 12 doesn't support this any more for domains you don't own.
This commit is contained in:
parent
81a89ec939
commit
ba3a37f6df
5 changed files with 6 additions and 307 deletions
|
@ -117,104 +117,6 @@
|
||||||
android:configChanges="keyboard|keyboardHidden"
|
android:configChanges="keyboard|keyboardHidden"
|
||||||
android:label="@string/station_details_activity_title"
|
android:label="@string/station_details_activity_title"
|
||||||
android:taskAffinity="de.schildbach.oeffi.stations">
|
android:taskAffinity="de.schildbach.oeffi.stations">
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
|
||||||
<data android:host="oeffi.schildbach.de" />
|
|
||||||
<data android:pathPrefix="/station/" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="qr.bvg.de" />
|
|
||||||
<data android:pathPrefix="/h" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="mobil.s-bahn-berlin.de" />
|
|
||||||
<data android:path="/" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="wap.rmv.de" />
|
|
||||||
<data android:pathPrefix="/mobil/tag/request.do" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="m.vrn.de" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="www.mvg-live.de" />
|
|
||||||
<data android:pathPrefix="/qr" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="www.rheinbahn.de" />
|
|
||||||
<data android:pathPrefix="/QRBarcode/HS" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="mobil.vvs.de" />
|
|
||||||
<data android:pathPrefix="/mob/DMR" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="m.qando.at" />
|
|
||||||
<data android:pathPrefix="/qr" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".stations.DecodeForeignActivity"
|
|
||||||
android:exported="true"
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:taskAffinity="de.schildbach.oeffi.stations"
|
|
||||||
android:theme="@style/My.Theme.Translucent">
|
|
||||||
<intent-filter android:label="@string/stations_station_details_intentfilter_title">
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:host="www.rmv.de" />
|
|
||||||
<data android:pathPrefix="/t/d" />
|
|
||||||
<data android:scheme="http" />
|
|
||||||
<data android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|
|
@ -134,7 +134,6 @@
|
||||||
<string name="stations_search_list_empty">Keine Haltestellen gefunden</string>
|
<string name="stations_search_list_empty">Keine Haltestellen gefunden</string>
|
||||||
|
|
||||||
<!-- station details -->
|
<!-- station details -->
|
||||||
<string name="stations_station_details_intentfilter_title">Abfahrtszeiten an dieser Haltestelle</string>
|
|
||||||
<string name="stations_station_details_action_favorite_title">Favorit</string>
|
<string name="stations_station_details_action_favorite_title">Favorit</string>
|
||||||
<string name="stations_station_details_progress">Lade Abfahrtszeiten…</string>
|
<string name="stations_station_details_progress">Lade Abfahrtszeiten…</string>
|
||||||
<string name="stations_station_details_list_empty">Keine Abfahrten</string>
|
<string name="stations_station_details_list_empty">Keine Abfahrten</string>
|
||||||
|
|
|
@ -136,7 +136,6 @@
|
||||||
<string name="stations_search_list_empty">No stations found</string>
|
<string name="stations_search_list_empty">No stations found</string>
|
||||||
|
|
||||||
<!-- station details -->
|
<!-- station details -->
|
||||||
<string name="stations_station_details_intentfilter_title">Departure times of this station</string>
|
|
||||||
<string name="stations_station_details_action_favorite_title">Favorite</string>
|
<string name="stations_station_details_action_favorite_title">Favorite</string>
|
||||||
<string name="stations_station_details_progress">Loading departures…</string>
|
<string name="stations_station_details_progress">Loading departures…</string>
|
||||||
<string name="stations_station_details_list_empty">No departures</string>
|
<string name="stations_station_details_list_empty">No departures</string>
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright the original author or authors.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.schildbach.oeffi.stations;
|
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import androidx.activity.ComponentActivity;
|
|
||||||
import de.schildbach.oeffi.Application;
|
|
||||||
import de.schildbach.oeffi.R;
|
|
||||||
import de.schildbach.oeffi.util.DialogBuilder;
|
|
||||||
import de.schildbach.pte.NetworkId;
|
|
||||||
import de.schildbach.pte.dto.Location;
|
|
||||||
import de.schildbach.pte.dto.LocationType;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.Callback;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class DecodeForeignActivity extends ComponentActivity {
|
|
||||||
private static final Pattern PATTERN_META_REFRESH = Pattern
|
|
||||||
.compile("<meta\\s+http-equiv=\"refresh\"\\s+content=\"0;\\s+URL=([^\"]*)\"");
|
|
||||||
|
|
||||||
private Application application;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
this.application = (Application) getApplication();
|
|
||||||
|
|
||||||
final Intent intent = getIntent();
|
|
||||||
final Uri uri = intent.getData();
|
|
||||||
|
|
||||||
if (uri != null && uri.getScheme().equals("http")) {
|
|
||||||
final String host = uri.getHost();
|
|
||||||
final String path = uri.getPath().trim();
|
|
||||||
|
|
||||||
if ("www.rmv.de".equals(host)) {
|
|
||||||
final Matcher m = Pattern.compile("/t/d(\\d+)").matcher(path);
|
|
||||||
if (m.matches()) {
|
|
||||||
final ProgressDialog progressDialog = ProgressDialog.show(DecodeForeignActivity.this, null,
|
|
||||||
getString(R.string.stations_decode_foreign_progress), true, true, dialog -> finish());
|
|
||||||
progressDialog.setCanceledOnTouchOutside(false);
|
|
||||||
|
|
||||||
final Request.Builder request = new Request.Builder();
|
|
||||||
request.url(HttpUrl.parse(uri.toString()));
|
|
||||||
final Call call = application.okHttpClient().newCall(request.build());
|
|
||||||
call.enqueue(new Callback() {
|
|
||||||
public void onResponse(final Call call, final Response r) throws IOException {
|
|
||||||
try (final Response response = r) {
|
|
||||||
if (response.isSuccessful()) {
|
|
||||||
final Matcher mRefresh = PATTERN_META_REFRESH.matcher(response.body().string());
|
|
||||||
if (mRefresh.find()) {
|
|
||||||
final Uri refreshUri = Uri.parse(mRefresh.group(1));
|
|
||||||
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
if ("mobil.rmv.de".equals(refreshUri.getHost())
|
|
||||||
&& "/mobile".equals(refreshUri.getPath())) {
|
|
||||||
final String id = refreshUri.getQueryParameter("id");
|
|
||||||
StationDetailsActivity.start(DecodeForeignActivity.this,
|
|
||||||
NetworkId.NVV, new Location(LocationType.STATION, id));
|
|
||||||
finish();
|
|
||||||
} else {
|
|
||||||
errorDialog(R.string.stations_decode_foreign_failed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
onFail();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onFail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFailure(final Call call, final IOException x) {
|
|
||||||
onFail();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFail() {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
errorDialog(R.string.stations_decode_foreign_failed);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("cannot handle path: '" + path + "'");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("cannot handle host: '" + host + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void errorDialog(final int resId) {
|
|
||||||
final DialogBuilder builder = DialogBuilder.warn(this, 0);
|
|
||||||
builder.setMessage(resId);
|
|
||||||
builder.setPositiveButton("Ok", (dialog, which) -> finish());
|
|
||||||
builder.setOnCancelListener(dialog -> finish());
|
|
||||||
builder.show();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -75,8 +75,6 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
@ -195,86 +193,12 @@ public class StationDetailsActivity extends OeffiActivity implements StationsAwa
|
||||||
resultStatusView = findViewById(R.id.stations_station_details_result_status);
|
resultStatusView = findViewById(R.id.stations_station_details_result_status);
|
||||||
|
|
||||||
final Intent intent = getIntent();
|
final Intent intent = getIntent();
|
||||||
final Uri uri = intent.getData();
|
final NetworkId network = (NetworkId) checkNotNull(intent.getSerializableExtra(INTENT_EXTRA_NETWORK));
|
||||||
|
final Station station = new Station(network, (Location) intent.getSerializableExtra(INTENT_EXTRA_STATION));
|
||||||
if (uri != null && uri.getScheme().equals("http")) {
|
if (intent.hasExtra(INTENT_EXTRA_DEPARTURES))
|
||||||
log.info("Got intent: {}", intent);
|
station.departures = (List<Departure>) intent.getSerializableExtra(INTENT_EXTRA_DEPARTURES);
|
||||||
|
selectStation(station);
|
||||||
final String host = uri.getHost();
|
statusMessage(getString(R.string.stations_station_details_progress));
|
||||||
final String path = uri.getPath().trim();
|
|
||||||
|
|
||||||
if ("oeffi.schildbach.de".equals(host)) {
|
|
||||||
final NetworkId network = NetworkId.valueOf(uri.getQueryParameter("network").toUpperCase());
|
|
||||||
final String stationId = uri.getQueryParameter("id");
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else if ("qr.bvg.de".equals(host)) {
|
|
||||||
final Matcher m = Pattern.compile("/h(\\d+)").matcher(path);
|
|
||||||
if (m.matches()) {
|
|
||||||
final NetworkId network = NetworkId.BVG;
|
|
||||||
String stationId = bvgStationIdNfcToQr(m.group(1));
|
|
||||||
if (stationId.length() <= 6) // mast
|
|
||||||
stationId = '~' + stationId;
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("could not parse path: '" + path + "'");
|
|
||||||
}
|
|
||||||
} else if ("mobil.s-bahn-berlin.de".equals(host)) {
|
|
||||||
if ("/".equals(path)) {
|
|
||||||
final NetworkId network = NetworkId.VBB;
|
|
||||||
final String qr = uri.getQueryParameter("QR");
|
|
||||||
final String stationId = qr != null ? qr : uri.getQueryParameter("qr");
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("could not parse path: '" + path + "'");
|
|
||||||
}
|
|
||||||
} else if ("www.mvg-live.de".equals(host)) {
|
|
||||||
final Matcher m = Pattern.compile("/qr/(\\d+)-\\d*-\\d*").matcher(path);
|
|
||||||
if (m.matches()) {
|
|
||||||
final NetworkId network = NetworkId.MVV;
|
|
||||||
final String stationId = m.group(1);
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("could not parse path: '" + path + "'");
|
|
||||||
}
|
|
||||||
} else if ("wap.rmv.de".equals(host)) {
|
|
||||||
final NetworkId network = NetworkId.NVV;
|
|
||||||
final String stationId = uri.getQueryParameter("id");
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else if ("m.vrn.de".equals(host)) {
|
|
||||||
final Matcher m = Pattern.compile("/(\\d+)").matcher(path);
|
|
||||||
if (m.matches()) {
|
|
||||||
final NetworkId network = NetworkId.VRN;
|
|
||||||
final String stationId = Integer.toString(Integer.parseInt(m.group(1)) + 6000000);
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("could not parse path: '" + path + "'");
|
|
||||||
}
|
|
||||||
} else if ("www.rheinbahn.de".equals(host)) {
|
|
||||||
final Matcher m = Pattern.compile("/QRBarcode/HS/(\\d+)_\\d*.html").matcher(path);
|
|
||||||
if (m.matches()) {
|
|
||||||
final NetworkId network = NetworkId.VRR;
|
|
||||||
final String stationId = Integer.toString(Integer.parseInt(m.group(1)) + 20000000);
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION, stationId, null, null)));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("could not parse path: '" + path + "'");
|
|
||||||
}
|
|
||||||
} else if ("mobil.vvs.de".equals(host)) {
|
|
||||||
final NetworkId network = NetworkId.VVS;
|
|
||||||
final int stationId = Integer.parseInt(uri.getQueryParameter("name_dm"));
|
|
||||||
// final String lineId = uri.getQueryParameter("line");
|
|
||||||
selectStation(new Station(network, new Location(LocationType.STATION,
|
|
||||||
Integer.toString(stationId < 10000 ? stationId + 5000000 : stationId), null, null)));
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("cannot handle host: '" + host + "'");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final NetworkId network = (NetworkId) checkNotNull(getIntent().getSerializableExtra(INTENT_EXTRA_NETWORK));
|
|
||||||
final Station station = new Station(network, (Location) intent.getSerializableExtra(INTENT_EXTRA_STATION));
|
|
||||||
if (intent.hasExtra(INTENT_EXTRA_DEPARTURES))
|
|
||||||
station.departures = (List<Departure>) intent.getSerializableExtra(INTENT_EXTRA_DEPARTURES);
|
|
||||||
selectStation(station);
|
|
||||||
statusMessage(getString(R.string.stations_station_details_progress));
|
|
||||||
}
|
|
||||||
|
|
||||||
favoriteButton
|
favoriteButton
|
||||||
.setChecked(selectedFavState != null && selectedFavState == FavoriteStationsProvider.TYPE_FAVORITE);
|
.setChecked(selectedFavState != null && selectedFavState == FavoriteStationsProvider.TYPE_FAVORITE);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue