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