From e2d4f44897dec2b6c0016b7cb7c8b89caf729660 Mon Sep 17 00:00:00 2001 From: Nitorac <nitorac.r@gmail.com> Date: Wed, 7 Oct 2020 03:28:33 +0200 Subject: [PATCH] Full functionnal logic for webviews --- .../fr/nitorac/aurionweb/MainActivity.java | 7 ++ .../main/java/fr/nitorac/aurionweb/Utils.java | 64 +++++++--- .../aurionweb/aurionweb/AurionManager.java | 94 +++++++------- .../aurionweb/aurionweb/AurionSession.java | 24 +++- .../aurionweb/aurionweb/AurionView.java | 7 -- .../aurionweb/CheckConnectionTask.java | 21 ++-- .../fragments/AurionViewFragment.java | 119 ++++++++++++++++-- .../fragments/calendar/CalendarFragment.java | 44 +++---- .../fragments/home/HomeFragment.java | 33 ++--- .../notifications/NotificationsFragment.java | 34 ----- app/src/main/res/layout/activity_main.xml | 3 +- .../main/res/layout/fragment_aurionview.xml | 15 +++ app/src/main/res/menu/bottom_nav_menu.xml | 2 +- .../main/res/navigation/mobile_navigation.xml | 4 +- app/src/main/res/raw/aurionweb_ensiie_fr.pem | 80 ++++++------ 15 files changed, 335 insertions(+), 216 deletions(-) delete mode 100644 app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionView.java create mode 100644 app/src/main/res/layout/fragment_aurionview.xml diff --git a/app/src/main/java/fr/nitorac/aurionweb/MainActivity.java b/app/src/main/java/fr/nitorac/aurionweb/MainActivity.java index d1e48ad..cf4a05a 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/MainActivity.java +++ b/app/src/main/java/fr/nitorac/aurionweb/MainActivity.java @@ -1,12 +1,14 @@ package fr.nitorac.aurionweb; import android.os.Bundle; +import android.util.SparseArray; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.navigation.ui.NavigationUI; @@ -25,6 +27,11 @@ public class MainActivity extends AppCompatActivity { private static MainActivity mainActivity; + public final static String SAVED_STATE_CONTAINER_KEY = "ContainerKey"; + public final static String SAVED_STATE_CURRENT_TAB_KEY = "CurrentTabKey"; + private SparseArray<Fragment.SavedState> savedStateSparseArray = new SparseArray<>(); + private int currentSelectedId = R.id.navigation_home; + @Override protected void onCreate(Bundle savedInstanceState) { mainActivity = this; diff --git a/app/src/main/java/fr/nitorac/aurionweb/Utils.java b/app/src/main/java/fr/nitorac/aurionweb/Utils.java index fa04ee7..3a165f6 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/Utils.java +++ b/app/src/main/java/fr/nitorac/aurionweb/Utils.java @@ -2,6 +2,7 @@ package fr.nitorac.aurionweb; import android.content.Context; import android.graphics.Point; +import android.util.Log; import android.view.Display; import android.view.WindowManager; @@ -18,6 +19,7 @@ import java.net.URLConnection; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.text.CharacterIterator; import java.text.Normalizer; @@ -31,37 +33,61 @@ public class Utils { public final static String BASE_SSL_URL = "https://ranini.iiens.net/aurionweb-check/cert.php?site="; private static SSLContext sslContext; + private static Certificate casCert; + private static Certificate aurionCert; public static Connection wrapSSL(String url) throws GeneralSecurityException, IOException { return Jsoup.connect(url) .sslSocketFactory(getContextForTrustedCertificates(MainActivity.getInstance().getApplicationContext()).getSocketFactory()); } - // Comme les certificats SSL de cas.ensiie.fr et aurionweb.ensiie.fr sont auto-signés, Android les refuse - // - // Ici on indique à Android qu'on fait confiance à uniquement ces 2 certificats - public static SSLContext getContextForTrustedCertificates(Context c) throws GeneralSecurityException, IOException { - if(sslContext == null){ - CertificateFactory cf = CertificateFactory.getInstance("X.509"); + public static CertificateFactory getSSLFactory() throws CertificateException { + return CertificateFactory.getInstance("X.509"); + } - // Fetch certificate from my perso - InputStream casInput; - InputStream aurionInput; + public static Certificate getCasCert(Context c) throws CertificateException { + if (casCert == null){ + InputStream input; + try{ + URLConnection conn = new URL(BASE_SSL_URL + "cas").openConnection(); + conn.connect(); + input = new BufferedInputStream(conn.getInputStream()); + }catch (IOException e){ + e.printStackTrace(); + Log.e("SSLCertFetch", "Can't get remote SSL cas certificate, fallback on local one"); + input = c.getResources().openRawResource(R.raw.cas_ensiie_fr); + } + casCert = getSSLFactory().generateCertificate(input); + } + return casCert; + } + + public static Certificate getAurionCert(Context c) throws CertificateException { + if (aurionCert == null){ + InputStream input; try{ - URLConnection casConn = new URL(BASE_SSL_URL + "cas").openConnection(); - URLConnection aurionConn = new URL(BASE_SSL_URL + "aurion").openConnection(); - casConn.connect(); - aurionConn.connect(); - casInput = new BufferedInputStream(casConn.getInputStream()); - aurionInput = new BufferedInputStream(aurionConn.getInputStream()); + URLConnection conn = new URL(BASE_SSL_URL + "aurion").openConnection(); + conn.connect(); + input = new BufferedInputStream(conn.getInputStream()); }catch (IOException e){ e.printStackTrace(); - casInput = c.getResources().openRawResource(R.raw.cas_ensiie_fr); - aurionInput = c.getResources().openRawResource(R.raw.aurionweb_ensiie_fr); + Log.e("SSLCertFetch", "Can't get remote SSL aurion certificate, fallback on local one"); + input = c.getResources().openRawResource(R.raw.aurionweb_ensiie_fr); } + aurionCert = getSSLFactory().generateCertificate(input); + } + return aurionCert; + } - Certificate cas = cf.generateCertificate(casInput); - Certificate aurionweb = cf.generateCertificate(aurionInput); + // Comme les certificats SSL de cas.ensiie.fr et aurionweb.ensiie.fr sont auto-signés, Android les refuse + // + // Ici on indique à Android qu'on fait confiance à uniquement ces 2 certificats + public static SSLContext getContextForTrustedCertificates(Context c) throws GeneralSecurityException, IOException { + CertificateFactory cf = getSSLFactory(); + if(sslContext == null){ + // Fetch certificate from my perso + Certificate cas = getCasCert(c); + Certificate aurionweb = getAurionCert(c); // Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); diff --git a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionManager.java b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionManager.java index 9b1be15..91c1a1e 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionManager.java +++ b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionManager.java @@ -19,6 +19,7 @@ import org.jsoup.nodes.Document; import java.io.IOException; import java.security.GeneralSecurityException; +import java.util.function.Consumer; import fr.nitorac.aurionweb.R; import fr.nitorac.aurionweb.StorageManager; @@ -33,6 +34,8 @@ public class AurionManager { } + + public boolean checkPassword(AurionSession session, AurionCred cred) throws GeneralSecurityException { if(session == null){ session = new AurionSession(); @@ -47,8 +50,36 @@ public class AurionManager { } } + public Document reachMyEdtFromInit(AurionSession session) throws IOException, GeneralSecurityException { + // On charge une fois la page pour valider un affichage fictif (cote server aurion) + // Requête effective permettant la validation de l'authentification sur CAS + Connection.Response resp = Utils.wrapSSL("https://aurionweb.ensiie.fr/faces/MainMenuPage.xhtml") + .method(Connection.Method.POST) + .followRedirects(true) + .header("Cache-Control", "max-age=0") + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Host", "aurionweb.ensiie.fr") + .header("Origin", "https://aurionweb.ensiie.fr") + .header("Referer", "https://aurionweb.ensiie.fr/") + .header("Upgrade-Insecure-Requests", "1") + .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36") + .cookie("JSESSIONID", session.getJSESSIONID()) + .data("form", "form") + //.data("form:largeurDivCenter", "1219") + //.data("form:sauvegarde", "") + .data("form:sidebar", "form:sidebar") + .data("form:sidebar_menuid", session.getSubmenuId()) + .data("javax.faces.ViewState", session.getViewState()) + .execute(); + Document respDoc = resp.parse(); + session.parseViewState(respDoc); + + return respDoc; + } + // Instancie une connection vers AurionWeb - public Document initConnection(AurionSession AurionSession, String username, String pwd) throws IOException, GeneralSecurityException { + public Document initConnection(AurionSession session, String username, String pwd) throws IOException, GeneralSecurityException { + session.clear(); // Première connection pour récupérer un String "execution" nécessaire à la connection Connection.Response initRes = Utils.wrapSSL("https://cas.ensiie.fr/login?service=https%3A%2F%2Faurionweb.ensiie.fr%2F%2Flogin%2Fcas") .method(Connection.Method.GET) @@ -76,12 +107,12 @@ public class AurionManager { secConn.data("password", pwd); Connection.Response sec = secConn.execute(); Document doc1 = sec.parse(); - AurionSession.parseViewState(doc1); - AurionSession.setJSESSIONID(sec.cookie("JSESSIONID")); + session.parseViewState(doc1); + session.setJSESSIONID(sec.cookie("JSESSIONID")); //On trouve le form ID - AurionSession.parseConnectMenuFormId(doc1); + session.parseConnectMenuFormId(doc1); //On trouve l'ID du bouton Emploi du temps (pour les requêtes) - AurionSession.parseConnectMenuId(doc1); + session.parseConnectMenuId(doc1); //Requête effective permettant la validation de l'authentification sur CAS Connection.Response tmp = Utils.wrapSSL("https://aurionweb.ensiie.fr/faces/MainMenuPage.xhtml") .method(Connection.Method.POST) @@ -94,51 +125,30 @@ public class AurionManager { .header("Faces-Request", "partial/ajax") .header("Upgrade-Insecure-Requests", "1") .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36") - .cookie("JSESSIONID", AurionSession.getJSESSIONID()) + .cookie("JSESSIONID", session.getJSESSIONID()) .data("javax.faces.partial.ajax", "true") - .data("javax.faces.source", AurionSession.getMenuFormId()) - .data("javax.faces.partial.execute", AurionSession.getMenuFormId()) + .data("javax.faces.source", session.getMenuFormId()) + .data("javax.faces.partial.execute", session.getMenuFormId()) .data("javax.faces.partial.render", "form:sidebar") - .data(AurionSession.getMenuFormId(), AurionSession.getMenuFormId()) - .data("webscolaapp.Sidebar.ID_SUBMENU", AurionSession.getMenuId()) + .data(session.getMenuFormId(), session.getMenuFormId()) + .data("webscolaapp.Sidebar.ID_SUBMENU", session.getMenuId()) .data("form", "form") //.data("form:largeurDivCenter", "1219") //.data("form:sauvegarde", "") - .data("javax.faces.ViewState", AurionSession.getViewState()) + .data("javax.faces.ViewState", session.getViewState()) .execute(); Document doc2 = tmp.parse(); - AurionSession.parseViewState(doc2); - AurionSession.parseConnectSubmenuId(doc2); - // On charge une fois la page pour valider un affichage fictif (cote server aurion) - // Requête effective permettant la validation de l'authentification sur CAS - Connection.Response resp = Utils.wrapSSL("https://aurionweb.ensiie.fr/faces/MainMenuPage.xhtml") - .method(Connection.Method.POST) - .followRedirects(true) - .header("Cache-Control", "max-age=0") - .header("Content-Type", "application/x-www-form-urlencoded") - .header("Host", "aurionweb.ensiie.fr") - .header("Origin", "https://aurionweb.ensiie.fr") - .header("Referer", "https://aurionweb.ensiie.fr/") - .header("Upgrade-Insecure-Requests", "1") - .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36") - .cookie("JSESSIONID", AurionSession.getJSESSIONID()) - .data("form", "form") - //.data("form:largeurDivCenter", "1219") - //.data("form:sauvegarde", "") - .data("form:sidebar", "form:sidebar") - .data("form:sidebar_menuid", AurionSession.getSubmenuId()) - .data("javax.faces.ViewState", AurionSession.getViewState()) - .execute(); - Document respDoc = resp.parse(); - //On trouve le formId du ChoixPlanning - AurionSession.parseChoixPlanningFormId(respDoc); - //On trouve l'id du bouton 'Voir planning' necéssaire aux requêtes - AurionSession.parseChoixPlanningSubmitBtnId(respDoc); - AurionSession.parseViewState(respDoc); - return respDoc; + session.parseViewState(doc2); + session.parseConnectSubmenuId(doc2); + + return doc2; + } + + public void spawnLoginDialog(Context c){ + spawnLoginDialog(c, (ignored) -> {}); } - public void spawnLoginDialog(Context c) { + public void spawnLoginDialog(Context c, Consumer<Void> callback) { final MaterialDialog dialog = new MaterialDialog(c, new BottomSheet(LayoutMode.MATCH_PARENT)) .title(null, "Connexion AurionWeb") .icon(null, ContextCompat.getDrawable(c, R.drawable.ic_login)) @@ -209,8 +219,6 @@ public class AurionManager { dialog.show(); } - - public static AurionManager getInstance(){ if(instance == null){ instance = new AurionManager(); diff --git a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionSession.java b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionSession.java index 996e47d..a7db5bb 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionSession.java +++ b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionSession.java @@ -107,15 +107,18 @@ public class AurionSession { public boolean parseConnectSubmenuId(Document doc) { doc = setLastDoc(doc); //On va maintenant trouver un ID de la forme '2_1' qui correspond à l'ID du lien "Planning d'un étudiant au choix" - Element liSubmenuID = Jsoup.parse(doc.getElementById("form:sidebar").text()).getElementsByTag("li").stream().filter(e -> Utils.stripAccents(e.text()).equalsIgnoreCase("Planning d'un etudiant au choix")).findFirst().orElse(null); + Element liSubmenuID = Jsoup.parse(doc.getElementById("form:sidebar").text()).getElementsByTag("li").stream().filter(e -> e.childNodeSize() == 1 && Utils.stripAccents(e.text()).contains("Mon planning")).findFirst().orElse(null); if (liSubmenuID != null) { - Matcher submenuMatcher = liSubmenuPattern.matcher(liSubmenuID.child(0).attr("onclick")); + String onclickAttr = liSubmenuID.child(0).attr("onclick"); + Matcher submenuMatcher = liSubmenuPattern.matcher(onclickAttr); if (submenuMatcher.find()) { submenuId = submenuMatcher.group(1); return true; + }else{ + Log.e(TAG, "Impossible de trouver le submenuID dans l'attribut"); } } else { - Log.e(TAG, "Impossible de trouver un sous menu de tag 'li' avec 'Planning d'un étudiant au choix' comme texte !"); + Log.e(TAG, "Impossible de trouver un sous menu de tag 'li' avec 'Mon planning' comme texte !"); } return false; } @@ -171,8 +174,21 @@ public class AurionSession { } } - public Document setLastDoc(Document doc) { return doc == null ? getLastDoc() : (lastDoc = doc); } + + + public void clear(){ + this.choixpFormId = ""; + this.choixpSubmitId = ""; + this.elemsPopupId = new ArrayList<>(); + this.JSESSIONID = ""; + this.lastDoc = null; + this.menuFormId = ""; + this.menuId = ""; + this.planningFormId = ""; + this.submenuId = ""; + this.viewState = ""; + } } diff --git a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionView.java b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionView.java deleted file mode 100644 index 1b13e02..0000000 --- a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/AurionView.java +++ /dev/null @@ -1,7 +0,0 @@ -package fr.nitorac.aurionweb.aurionweb; - -public class AurionView { - public AurionView(){ - - } -} diff --git a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/CheckConnectionTask.java b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/CheckConnectionTask.java index 14f40a6..5f53c5f 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/aurionweb/CheckConnectionTask.java +++ b/app/src/main/java/fr/nitorac/aurionweb/aurionweb/CheckConnectionTask.java @@ -9,21 +9,24 @@ import com.afollestad.materialdialogs.bottomsheets.BottomSheet; import com.afollestad.materialdialogs.customview.DialogCustomViewExtKt; import java.security.GeneralSecurityException; +import java.util.function.Consumer; import fr.nitorac.aurionweb.R; public class CheckConnectionTask extends AsyncTask<AurionCred, Void, Boolean> { private MaterialDialog loading; - private ConnectionCheck callback; + private Consumer<Boolean> callback; + private Consumer<AurionSession> networkStuff; private AurionSession session; - public CheckConnectionTask(Context c, ConnectionCheck callback){ - this(c, new AurionSession(), callback); + public CheckConnectionTask(Context c, Consumer<Boolean> callback){ + this(c, new AurionSession(), callback, (ign) -> {}); } - public CheckConnectionTask(Context c, AurionSession session, ConnectionCheck callback){ + public CheckConnectionTask(Context c, AurionSession session, Consumer<Boolean> callback, Consumer<AurionSession> networkStuff){ this.callback = callback; + this.networkStuff = networkStuff; this.session = session; loading = new MaterialDialog(c, new BottomSheet(LayoutMode.WRAP_CONTENT)) .cancelable(false) @@ -44,20 +47,18 @@ public class CheckConnectionTask extends AsyncTask<AurionCred, Void, Boolean> { protected void onPostExecute(Boolean res) { super.onPostExecute(res); loading.dismiss(); - callback.onResult(res); + callback.accept(res); } @Override protected Boolean doInBackground(AurionCred... cred) { try { - return AurionManager.getInstance().checkPassword(session, cred[0]); + boolean res = AurionManager.getInstance().checkPassword(session, cred[0]); + networkStuff.accept(session); + return res; } catch (GeneralSecurityException e) { e.printStackTrace(); return false; } } - - public interface ConnectionCheck { - void onResult(Boolean res); - } } diff --git a/app/src/main/java/fr/nitorac/aurionweb/fragments/AurionViewFragment.java b/app/src/main/java/fr/nitorac/aurionweb/fragments/AurionViewFragment.java index 008e8ee..df7ebf8 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/fragments/AurionViewFragment.java +++ b/app/src/main/java/fr/nitorac/aurionweb/fragments/AurionViewFragment.java @@ -1,7 +1,29 @@ package fr.nitorac.aurionweb.fragments; +import android.content.Context; +import android.net.http.SslError; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.CookieManager; +import android.webkit.SslErrorHandler; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Toast; + +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.HashMap; +import java.util.Map; + +import fr.nitorac.aurionweb.R; +import fr.nitorac.aurionweb.Utils; import fr.nitorac.aurionweb.aurionweb.AurionManager; import fr.nitorac.aurionweb.aurionweb.AurionSession; import fr.nitorac.aurionweb.aurionweb.CheckConnectionTask; @@ -9,22 +31,103 @@ import fr.nitorac.aurionweb.security.SecurityManager; public abstract class AurionViewFragment extends Fragment { - private AurionSession currentSession = new AurionSession(); - - public abstract String getName(); + protected AurionSession currentSession = new AurionSession(); + protected WebView webView; + private View rootView; public abstract void preload(); - @Override - public void onResume() { - super.onResume(); + public void pageFinished(WebView view, String url){ + + } + + public void networkInit(AurionSession session){ + + } + + protected void initLoad(){ CheckConnectionTask check = new CheckConnectionTask(getContext(), currentSession, res -> { if(res){ + setCookie(); preload(); }else{ - AurionManager.getInstance().spawnLoginDialog(getContext()); + AurionManager.getInstance().spawnLoginDialog(getContext(), (ignored) ->{ + setCookie(); + preload(); + }); } - }); + }, this::networkInit); check.execute(SecurityManager.creds); } + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + if(rootView == null){ + rootView = inflater.inflate(R.layout.fragment_aurionview, container, false); + + webView = rootView.findViewById(R.id.aurionView); + + webView.getSettings().setSupportZoom(true); + webView.getSettings().setJavaScriptEnabled(true); + + webView.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + pageFinished(view, url); + if(url.contains("cas.ensiie.fr")){ + initLoad(); + } + super.onPageFinished(view, url); + } + + @Override + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + Log.e("WebClient", description); + } + + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError er) { + Context c = AurionViewFragment.this.getContext(); + try{ + Certificate cas = Utils.getCasCert(c); + Certificate aurion = Utils.getAurionCert(c); + handler.proceed(); + }catch (CertificateException e){ + e.printStackTrace(); + Toast.makeText(c, "Erreur de certificat SSL : " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); + handler.cancel(); + } + } + + }); + + initLoad(); + + if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true); + CookieManager.getInstance().removeAllCookies(bool -> {}); + } + } + + return rootView; + } + + @Override + public void onResume() { + super.onResume(); + setCookie(); + } + + public void setCookie(){ + CookieManager.getInstance().setCookie("https://aurionweb.ensiie.fr", "JSESSIONID=" + currentSession.getJSESSIONID()); + } + + public Map<String, String> getHeaders(){ + HashMap<String, String> res = new HashMap<>(); + res.put("Accept", "*/*"); + res.put("Accept-Encoding", "gzip, deflate"); + res.put("Cache-Control", "no-cache"); + + return res; + } } diff --git a/app/src/main/java/fr/nitorac/aurionweb/fragments/calendar/CalendarFragment.java b/app/src/main/java/fr/nitorac/aurionweb/fragments/calendar/CalendarFragment.java index bb8a1e6..192c3c5 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/fragments/calendar/CalendarFragment.java +++ b/app/src/main/java/fr/nitorac/aurionweb/fragments/calendar/CalendarFragment.java @@ -1,38 +1,38 @@ package fr.nitorac.aurionweb.fragments.calendar; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; +import android.util.Log; +import android.widget.Toast; -import androidx.annotation.NonNull; -import androidx.lifecycle.ViewModelProviders; +import java.io.IOException; +import java.security.GeneralSecurityException; -import fr.nitorac.aurionweb.R; +import fr.nitorac.aurionweb.aurionweb.AurionManager; +import fr.nitorac.aurionweb.aurionweb.AurionSession; import fr.nitorac.aurionweb.fragments.AurionViewFragment; +import fr.nitorac.aurionweb.fragments.home.HomeFragment; public class CalendarFragment extends AurionViewFragment { - private CalendarViewModel calendarViewModel; - - public View onCreateView(@NonNull LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { - calendarViewModel = - ViewModelProviders.of(this).get(CalendarViewModel.class); - View root = inflater.inflate(R.layout.fragment_calendar, container, false); - final TextView textView = root.findViewById(R.id.text_dashboard); - calendarViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); - return root; - } + public static final String AURION_CAL_URL = "https://aurionweb.ensiie.fr/faces/Planning.xhtml"; + private boolean failed = false; @Override - public String getName() { - return "Calendar"; + public void networkInit(AurionSession session) { + try { + AurionManager.getInstance().reachMyEdtFromInit(currentSession); + } catch (IOException | GeneralSecurityException e) { + e.printStackTrace(); + failed = true; + Log.e(getClass().getSimpleName(), "Impossible de charger le chemin vers l'emploi du temps (" + e.getLocalizedMessage() + ")"); + Toast.makeText(getContext(), "Impossible de charger le chemin vers l'emploi du temps (" + e.getLocalizedMessage() + ")", Toast.LENGTH_LONG).show(); + webView.loadUrl(HomeFragment.AURIONURL, getHeaders()); + } } @Override public void preload() { - + if(!failed){ + webView.loadUrl(AURION_CAL_URL, getHeaders()); + } } } \ No newline at end of file diff --git a/app/src/main/java/fr/nitorac/aurionweb/fragments/home/HomeFragment.java b/app/src/main/java/fr/nitorac/aurionweb/fragments/home/HomeFragment.java index 559acbd..8fc0e0b 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/fragments/home/HomeFragment.java +++ b/app/src/main/java/fr/nitorac/aurionweb/fragments/home/HomeFragment.java @@ -1,38 +1,25 @@ package fr.nitorac.aurionweb.fragments.home; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; +import android.util.Log; +import android.webkit.WebView; -import androidx.annotation.NonNull; -import androidx.lifecycle.ViewModelProviders; - -import fr.nitorac.aurionweb.R; import fr.nitorac.aurionweb.fragments.AurionViewFragment; public class HomeFragment extends AurionViewFragment { - private HomeViewModel homeViewModel; - - public View onCreateView(@NonNull LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { - homeViewModel = - ViewModelProviders.of(this).get(HomeViewModel.class); - View root = inflater.inflate(R.layout.fragment_home, container, false); - final TextView textView = root.findViewById(R.id.text_home); - homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); - return root; - } + public static final String AURIONURL = "https://aurionweb.ensiie.fr"; @Override - public String getName() { - return "Home"; + public void pageFinished(WebView view, String url) { + if(url.equals("https://aurionweb.ensiie.fr")){ + view.evaluateJavascript("$(\"#mobile-menu-btn\").click();", paRes -> { + Log.e("JSSS", paRes); + }); + } } @Override public void preload() { - + webView.loadUrl(AURIONURL, getHeaders()); } } \ No newline at end of file diff --git a/app/src/main/java/fr/nitorac/aurionweb/fragments/notifications/NotificationsFragment.java b/app/src/main/java/fr/nitorac/aurionweb/fragments/notifications/NotificationsFragment.java index 72fc48d..fda5e95 100644 --- a/app/src/main/java/fr/nitorac/aurionweb/fragments/notifications/NotificationsFragment.java +++ b/app/src/main/java/fr/nitorac/aurionweb/fragments/notifications/NotificationsFragment.java @@ -1,43 +1,9 @@ package fr.nitorac.aurionweb.fragments.notifications; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProviders; - -import fr.nitorac.aurionweb.R; import fr.nitorac.aurionweb.fragments.AurionViewFragment; public class NotificationsFragment extends AurionViewFragment { - private NotificationsViewModel notificationsViewModel; - - public View onCreateView(@NonNull LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { - notificationsViewModel = - ViewModelProviders.of(this).get(NotificationsViewModel.class); - View root = inflater.inflate(R.layout.fragment_notifications, container, false); - final TextView textView = root.findViewById(R.id.text_notifications); - notificationsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { - @Override - public void onChanged(@Nullable String s) { - textView.setText(s); - } - }); - return root; - } - - @Override - public String getName() { - return "Notif"; - } - @Override public void preload() { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 38c0aa8..d504aa5 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -3,8 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/container" android:layout_width="match_parent" - android:layout_height="match_parent" - android:paddingTop="?attr/actionBarSize"> + android:layout_height="match_parent"> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/nav_view" diff --git a/app/src/main/res/layout/fragment_aurionview.xml b/app/src/main/res/layout/fragment_aurionview.xml new file mode 100644 index 0000000..15b3bec --- /dev/null +++ b/app/src/main/res/layout/fragment_aurionview.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <WebView + android:id="@+id/aurionView" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml index 5485a38..994b53a 100644 --- a/app/src/main/res/menu/bottom_nav_menu.xml +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -7,7 +7,7 @@ android:title="@string/title_home" /> <item - android:id="@+id/navigation_dashboard" + android:id="@+id/navigation_calendar" android:icon="@drawable/ic_calendar" android:title="@string/title_calendar" /> diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 71c664b..75afbe9 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/mobile_navigation" - app:startDestination="@+id/navigation_home"> + app:startDestination="@+id/navigation_calendar"> <fragment android:id="@+id/navigation_home" @@ -12,7 +12,7 @@ tools:layout="@layout/fragment_home" /> <fragment - android:id="@+id/navigation_dashboard" + android:id="@+id/navigation_calendar" android:name="fr.nitorac.aurionweb.fragments.calendar.CalendarFragment" android:label="@string/title_calendar" tools:layout="@layout/fragment_calendar" /> diff --git a/app/src/main/res/raw/aurionweb_ensiie_fr.pem b/app/src/main/res/raw/aurionweb_ensiie_fr.pem index 4b1c5b4..e9c62cf 100644 --- a/app/src/main/res/raw/aurionweb_ensiie_fr.pem +++ b/app/src/main/res/raw/aurionweb_ensiie_fr.pem @@ -1,42 +1,40 @@ -----BEGIN CERTIFICATE----- -MIIHTzCCBjegAwIBAgIQCQtdJVL7YaPr+9+02mt9CzANBgkqhkiG9w0BAQsFADBk -MQswCQYDVQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDESMBAGA1UEBxMJ -QW1zdGVyZGFtMQ8wDQYDVQQKEwZURVJFTkExGDAWBgNVBAMTD1RFUkVOQSBTU0wg -Q0EgMzAeFw0xODA3MDQwMDAwMDBaFw0yMDEwMDYwMDAwMDBaMIGYMQswCQYDVQQG -EwJGUjETMBEGA1UEBxMKRVZSWSBDRURFWDFIMEYGA1UECgw/RWNvbGUgTmF0aW9u -YWxlIFN1cMOpcmlldXJlIGQnaW5mby4gcG91ciBsJ0luZC4gZXQgbCdFbnRyZXBy -aXNlMQwwCgYDVQQLEwNDUkkxHDAaBgNVBAMTE2F1cmlvbndlYi5lbnNpaWUuZnIw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnNDksvsGjgcM3ThkXVAx5 -xxJXoDUYbnuqdqyi0oA1uSjHVcC+4UgA2lw+ZY/FeCG7weAPejGZqqZhY6vEq54M -hysnNZH3VDgFUeixq1D8gEjOxkdOwXm88utvplan3PgcOIckt2BjsEbfxseX1v4u -4VDH5/99MeTBeAjxrknZPjWdILiPMx/9BgKKOHbfXhrKZoeZ6bfsEoVzKWjlAqPP -rxBYbAeX4kFZE0VWLrlqs2VNzKfsmvfm+GAKKf8h0iRlUM1lG8bBsmfxb0pjg9Tm -mVJgr2+8R89V1j59hFiBHjfyqYoSJNirUlhXuGFKeGOBzJm4jDReWHPe5BBthnk3 -AgMBAAGjggPGMIIDwjAfBgNVHSMEGDAWgBRn/YggFCeYxwnSJRm76VERY3VQYjAd -BgNVHQ4EFgQU9RX+8yvm3V3rbDKQz3s6FJegGqAwHgYDVR0RBBcwFYITYXVyaW9u -d2ViLmVuc2lpZS5mcjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH -AwEGCCsGAQUFBwMCMGsGA1UdHwRkMGIwL6AtoCuGKWh0dHA6Ly9jcmwzLmRpZ2lj -ZXJ0LmNvbS9URVJFTkFTU0xDQTMuY3JsMC+gLaArhilodHRwOi8vY3JsNC5kaWdp -Y2VydC5jb20vVEVSRU5BU1NMQ0EzLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwB -ATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgG -BmeBDAECAjBuBggrBgEFBQcBAQRiMGAwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw -LmRpZ2ljZXJ0LmNvbTA4BggrBgEFBQcwAoYsaHR0cDovL2NhY2VydHMuZGlnaWNl -cnQuY29tL1RFUkVOQVNTTENBMy5jcnQwDAYDVR0TAQH/BAIwADCCAfYGCisGAQQB -1nkCBAIEggHmBIIB4gHgAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN -3BAAAAFkZD6SfgAABAMARzBFAiEAhqeRjwyl7IWrb46mS4n+I31HxLNhDDLn9jEi -VN3Cip0CIDqnppqzhC6e3RHYFTXrvkdQjrzAw/LRtgJ+M9J2idNPAHYAh3W/51l8 -+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFkZD6TUwAABAMARzBFAiEA/CFX -dd1HUPCDZjMz+oqicI6H7UCUKTO1Y9ojCJwUFzECIGOU4F7s2gyV7j8rm/xF3Vw/ -jeP1nDWDpO/bs+6JO6XtAHcA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo -/csAAAFkZD6SwQAABAMASDBGAiEAuWbkrYVras5GeloBf4224WOv+ZRg+QV3xQGn -MmVTFtICIQCz73qOSo/HyT1Ctak7NWYwHlW/bRIu61Ol+U7LxZr01wB1ALvZ37wf -inG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAABZGQ+k3MAAAQDAEYwRAIgcZDt -pPgy3Jd100lSKUGqIPZ9okT8S2Q3umjmM+52DPICIBeX+iCxSIiIF3wQAo+B22Qo -GUzYVMEqpV5jN2iI4Y5VMA0GCSqGSIb3DQEBCwUAA4IBAQASfy7UQIOWiJhSSxJj -xwxhe1uyVn/+JNbaqNyDGGz0uL8hGZTt6SUGrjV+/RMnL0l8d5eApe73Chr5VcYn -3kcuY4B3EKzMEonuGuMOJmPzk65YWk015lHJc0t+GOMi0BN1Ven/DweDRlxIb18w -CM/Tvua27q0PBGPDjQ1m+QRZ9gaEU1XyqD7Cts4SFfjwxZL4EjAz/dQFsGfB4a4Z -l3l94e7vGZfMUOoORFkrV55Qm5zqodQyRv6A46M1v6+kfVMUPyppVCM2F54EPw6M -7r6RULICwobirLXdT4CajKB4bOIjm0e09zLzuij4TLAo34mOATG9DYV2HOFRsCem -NJBE ------END CERTIFICATE----- \ No newline at end of file +MIIHCjCCBPKgAwIBAgIRANdyPNmD81AD2b/IqSWUdQkwDQYJKoZIhvcNAQEMBQAw +RDELMAkGA1UEBhMCTkwxGTAXBgNVBAoTEEdFQU5UIFZlcmVuaWdpbmcxGjAYBgNV +BAMTEUdFQU5UIE9WIFJTQSBDQSA0MB4XDTIwMTAwNjAwMDAwMFoXDTIxMTAwNjIz +NTk1OVowgYwxCzAJBgNVBAYTAkZSMQ4wDAYDVQQREwU5MTAwMDEbMBkGA1UEBxMS +RXZyeS1Db3VyY291cm9ubmVzMSEwHwYDVQQJExgxIHBsYWNlIGRlIGxhIHJlc2lz +dGFuY2UxDzANBgNVBAoTBkVOU0lJRTEcMBoGA1UEAxMTYXVyaW9ud2ViLmVuc2lp +ZS5mcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7EAe+t9uAKTEbZ +ejoB0tGbzvF0KgXlkCGRiiEbs9h9ZPxlPMd5JOWvSYEtXgLS8eHoMxqf5O0l0uh4 +k2zC/QT5thuBaX8R2emFyWVbXcBoAkwv5HqVf2nxdpkDceHp08tVavMEVj9Fq9vU +xWR8DfULN3bj1UCxZYquj6oPcJopwXjmdelkuY8SAaQiYoKXSWQl2E95eIsxa8r3 +Utoi+CXEL0Is2JQ9xAcXfk44U02BZyyx5eq6ZJlVhHZpDhPrfntfTe5CkgH7syAh +KLJvKLEBtcUoMDkDVYOoEn/K/VQLTm1waBXTmTaBjwnlJRGw9QsQSsgXj/MwtpA9 +lr2zV3UCAwEAAaOCAqwwggKoMB8GA1UdIwQYMBaAFG8dNUkQbDL6WaCevIroH5W+ +cXoMMB0GA1UdDgQWBBRhcwiZVwXyqQSpOJ7l3v/dS3LZfzAOBgNVHQ8BAf8EBAMC +BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +SQYDVR0gBEIwQDA0BgsrBgEEAbIxAQICTzAlMCMGCCsGAQUFBwIBFhdodHRwczov +L3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgIwPwYDVR0fBDgwNjA0oDKgMIYuaHR0 +cDovL0dFQU5ULmNybC5zZWN0aWdvLmNvbS9HRUFOVE9WUlNBQ0E0LmNybDB1Bggr +BgEFBQcBAQRpMGcwOgYIKwYBBQUHMAKGLmh0dHA6Ly9HRUFOVC5jcnQuc2VjdGln +by5jb20vR0VBTlRPVlJTQUNBNC5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9HRUFO +VC5vY3NwLnNlY3RpZ28uY29tMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYAfT7y ++I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8NcAAAF0/QvDEwAABAMARzBFAiEA +p3ynLRM6hO8gORfWAU8TOpf79pTOjsQohuaP22uNOgMCIGQSeobl7DCoiDReazZc +mN8G5YeaUEKd0rirEeoivNtyAHYAlCC8Ho7VjWyIcx+CiyIsDdHaTV5sT5Q9YdtO +L1hNosIAAAF0/QvDOwAABAMARzBFAiBwWqJ0U51hmQ4sVaeNQOlsaStAq1/NVVaN +LgJYoQpUvgIhAIQ+fgb6CB5wyYhvRYHFknUrWrLq7IkEhgSIRYS3j7xVMB4GA1Ud +EQQXMBWCE2F1cmlvbndlYi5lbnNpaWUuZnIwDQYJKoZIhvcNAQEMBQADggIBABPL +QLUdza9YOXC8vz0mXKiCKugQFwEtBibHa65LSmzcn84QMaTqg3PrQBB3jBi3gdZe +FQEPGXQCTDZh+6bZnLVtk61YO9UXNZA3kDc+XZdMwupKjN2OokZ6iljmQDbdHm15 +HTsGhVFcTFqjyKmKFmS0ZYRQQFLQChK4Hr2U/LRfzT/b49JMGfkVXl7aETHUAfA4 +PuaQGoha4LzhTHBAejBmPQGZe5+Ms+HQ2OMvCN8ev4e4yCLx+nySKqq7x2iTeYHK +hIaVLBzTF2+uotQhszrsrbFpNsg3WR4VAKQEG7n7dZ5ruf2R4Ufsps9uKSEjh0ad +DD9UBJjUwqGrh+qZSt9KAhCbZfV+GuXVIp1UrzDx7V+sCu/kU2V7lKKbDwYdJkuD +BMpWFS0VMrIfje1SURwtEY7kGSzYTk0VACokMdJKxCMv7N6da3QK4jUpeIi2SJ04 +zdw+cxH5C7Zo4emySm1LhquLiMIeTtEI/o/vN26XmAj0TDVP99uqr2Hs83B7m71P +aV1lpjG7lWawuBNcePtUGZ36HzcXKqbtsigHhsnh2+EWa7fdTYMUupM4HQkcGTIt +y0MKNSgNCQF4Zo4a7GzkNvGnev5+1H0kX05Cg4L50cs043K7j6H2gbCXCAJ6PcPi +ve9d5bvkWBlPoBwfKvbG+j2/XrHt7SjoHvcygNv+ +-----END CERTIFICATE----- -- GitLab