diff --git a/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java b/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java index 5c38cad..ca14f48 100644 --- a/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java +++ b/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java @@ -1,120 +1,132 @@ /* BusTO (backend components) Copyright (C) 2016 Ludovico Pavesi 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 . */ package it.reyboz.bustorino.backend; +import android.util.Log; + import androidx.annotation.NonNull; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.net.URL; import java.net.URLEncoder; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicReference; public class GTTJSONFetcher implements ArrivalsFetcher { + private final String DEBUG_TAG = "GTTJSONFetcher-BusTO"; @Override @NonNull public Palina ReadArrivalTimesAll(String stopID, AtomicReference res) { URL url; Palina p = new Palina(stopID); String routename; String bacino; String content; JSONArray json; int howManyRoutes, howManyPassaggi, i, j, pos; // il misto inglese-italiano รจ un po' ridicolo ma tanto vale... JSONObject thisroute; JSONArray passaggi; try { - url = new URL("http://www.gtt.to.it/cms/index.php?option=com_gtt&task=palina.getTransitiOld&palina=" + URLEncoder.encode(stopID, "utf-8") + "&realtime=true"); + url = new URL("https://www.gtt.to.it/cms/index.php?option=com_gtt&task=palina.getTransitiOld&palina=" + URLEncoder.encode(stopID, "utf-8") + "&bacino=U&realtime=true&get_param=value"); } catch (Exception e) { res.set(result.PARSER_ERROR); return p; } + HashMap headers = new HashMap<>(); + //headers.put("Referer","https://www.gtt.to.it/cms/percorari/urbano?view=percorsi&bacino=U&linea=15&Regol=GE"); + headers.put("Host", "www.gtt.to.it"); - content = networkTools.queryURL(url, res); + content = networkTools.queryURL(url, res, headers); if(content == null) { + Log.w("GTTJSONFetcher", "NULL CONTENT"); return p; } try { json = new JSONArray(content); } catch(JSONException e) { + Log.w(DEBUG_TAG, "Error parsing JSON: \n"+content); + Log.w(DEBUG_TAG, e); res.set(result.PARSER_ERROR); + return p; } try { // returns [{"PassaggiRT":[],"Passaggi":[]}] for non existing stops! json.getJSONObject(0).getString("Linea"); // if we can get this, then there's something useful in the array. } catch(JSONException e) { + Log.w(DEBUG_TAG, "No existing lines"); res.set(result.EMPTY_RESULT_SET); return p; } howManyRoutes = json.length(); if(howManyRoutes == 0) { res.set(result.EMPTY_RESULT_SET); return p; } try { for(i = 0; i < howManyRoutes; i++) { thisroute = json.getJSONObject(i); routename = thisroute.getString("Linea"); try { bacino = thisroute.getString("Bacino"); } catch (JSONException ignored) { // if "Bacino" gets removed... bacino = "U"; } pos = p.addRoute(routename, thisroute.getString("Direzione"), FiveTNormalizer.decodeType(routename, bacino)); passaggi = thisroute.getJSONArray("PassaggiRT"); howManyPassaggi = passaggi.length(); for(j = 0; j < howManyPassaggi; j++) { String mPassaggio = passaggi.getString(j); if (mPassaggio.contains("__")){ mPassaggio = mPassaggio.replace("_", ""); } p.addPassaggio(mPassaggio.concat("*"), Passaggio.Source.GTTJSON, pos); } passaggi = thisroute.getJSONArray("PassaggiPR"); // now the non-real-time ones howManyPassaggi = passaggi.length(); for(j = 0; j < howManyPassaggi; j++) { p.addPassaggio(passaggi.getString(j), Passaggio.Source.GTTJSON, pos); } } } catch (JSONException e) { res.set(result.PARSER_ERROR); return p; } p.sortRoutes(); res.set(result.OK); return p; } @Override public Passaggio.Source getSourceForFetcher() { return Passaggio.Source.GTTJSON; } } diff --git a/src/it/reyboz/bustorino/backend/networkTools.java b/src/it/reyboz/bustorino/backend/networkTools.java index da540f7..d0285aa 100644 --- a/src/it/reyboz/bustorino/backend/networkTools.java +++ b/src/it/reyboz/bustorino/backend/networkTools.java @@ -1,173 +1,180 @@ /* BusTO - Arrival times for Turin public transports. Copyright (C) 2014 Valerio Bozzolan 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 . */ package it.reyboz.bustorino.backend; import androidx.annotation.Nullable; import android.util.Log; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Map; import java.util.Scanner; import java.util.concurrent.atomic.AtomicReference; public abstract class networkTools { static String getDOM(final URL url, final AtomicReference res) { //Log.d("asyncwget", "Catching URL in background: " + uri[0]); HttpURLConnection urlConnection; StringBuilder result = null; try { urlConnection = (HttpURLConnection) url.openConnection(); } catch(IOException e) { res.set(Fetcher.result.SERVER_ERROR); return null; } try { InputStream in = new BufferedInputStream( urlConnection.getInputStream()); BufferedReader reader = new BufferedReader( new InputStreamReader(in)); result = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { result.append(line); } } catch (Exception e) { //Log.e("asyncwget", e.getMessage()); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } if (result == null) { res.set(Fetcher.result.SERVER_ERROR); return null; } res.set(Fetcher.result.PARSER_ERROR); // will be set to "OK" later, this is a safety net in case StringBuilder returns null, the website returns an HTTP 204 or something like that. return result.toString(); } @Nullable static String queryURL(URL url, AtomicReference res){ return queryURL(url,res,null); } @Nullable static String queryURL(URL url, AtomicReference res, Map headers) { HttpURLConnection urlConnection; InputStream in; String s; try { urlConnection = (HttpURLConnection) url.openConnection(); } catch(IOException e) { + //e.printStackTrace(); res.set(Fetcher.result.SERVER_ERROR); // even when offline, urlConnection works fine. WHY. return null; } // TODO: make this configurable? - urlConnection.setConnectTimeout(5000); + urlConnection.setConnectTimeout(3000); urlConnection.setReadTimeout(10000); if(headers!= null){ for(String key : headers.keySet()){ urlConnection.setRequestProperty(key,headers.get(key)); } } res.set(Fetcher.result.SERVER_ERROR); // will be set to OK later try { in = urlConnection.getInputStream(); } catch (Exception e) { try { if(urlConnection.getResponseCode()==404) res.set(Fetcher.result.SERVER_ERROR_404); } catch (IOException e2) { e2.printStackTrace(); } return null; } //s = streamToString(in); try { final long startTime = System.currentTimeMillis(); s = parseStreamToString(in); final long endtime = System.currentTimeMillis(); Log.d("NetworkTools-queryURL","reading response took "+(endtime-startTime)+" millisec"); } catch (IOException e) { e.printStackTrace(); return null; } try { in.close(); - } catch(Exception ignored) {} + } catch(IOException ignored) { + //ignored.printStackTrace(); + } try { urlConnection.disconnect(); - } catch(Exception ignored) {} + } catch(Exception ignored) { + //ignored.printStackTrace(); + } if(s.length() == 0) { + Log.w("NET TOOLS", "string is empty"); return null; } else { + //Log.d("NET TOOLS", s); return s; } } // https://stackoverflow.com/a/5445161 static String streamToString(InputStream is) { Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } /** * New method, maybe faster, to read inputStream * also see https://stackoverflow.com/a/5445161 * @param is what to read * @return the String Read * @throws IOException from the InputStreamReader */ static String parseStreamToString(InputStream is) throws IOException{ final int bufferSize = 1024; final char[] buffer = new char[bufferSize]; final StringBuilder out = new StringBuilder(); InputStreamReader in = new InputStreamReader(is, "UTF-8"); int rsz= in.read(buffer, 0, buffer.length); while( rsz >0) { out.append(buffer, 0, rsz); rsz = in.read(buffer, 0, buffer.length); } return out.toString(); } static int failsafeParseInt(String str) { try { return Integer.parseInt(str); } catch(NumberFormatException e) { return 0; } } }