Archived
Login page now disallows visiting a domain other than the school's login page to prevent a successful login from another domain allowing access to the app's content
This commit is contained in:
@@ -18,7 +18,7 @@ import com.denizd.substitutionplan.R
|
||||
import com.denizd.substitutionplan.database.SubstRepository
|
||||
import com.denizd.substitutionplan.activities.Main
|
||||
import com.denizd.substitutionplan.models.Food
|
||||
import com.denizd.substitutionplan.models.Subst
|
||||
import com.denizd.substitutionplan.models.Substitution
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.jsoup.Jsoup
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -57,7 +57,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
|
||||
private val edit = prefs.edit()
|
||||
private var currentTime = ""
|
||||
private var currentFoodTime = ""
|
||||
private var substUrl = "https://djd4rkn355.github.io/subst.html"
|
||||
private var substUrl = "https://djd4rkn355.github.io/avh_substitutions.html"
|
||||
private var foodUrl = "https://djd4rkn355.github.io/food.html"
|
||||
|
||||
override fun doInBackground(vararg params: Void?): Void? {
|
||||
@@ -149,7 +149,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
|
||||
if (currentTime != prefs.getString("timeNew", "")) {
|
||||
val rows = doc.select("tr")
|
||||
val paragraphs = doc.select("p")
|
||||
val substArray = ArrayList<Subst>()
|
||||
val substArray = ArrayList<Substitution>()
|
||||
|
||||
val coursePreference = prefs.getString("courses", "") ?: ""
|
||||
val classPreference = prefs.getString("classes", "") ?: ""
|
||||
@@ -169,7 +169,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
|
||||
val row = rows[i]
|
||||
val cols = row.select("th")
|
||||
|
||||
val subst = Subst(
|
||||
val subst = Substitution(
|
||||
group = cols[0].text(),
|
||||
date = cols[1].text(),
|
||||
time = cols[2].text(),
|
||||
@@ -237,11 +237,12 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
|
||||
val notification = NotificationCompat.Builder(context, HelperFunctions.notificationChannelId)
|
||||
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
|
||||
.setCustomContentView(notificationLayout)
|
||||
.setSmallIcon(R.drawable.ic_avhlogo)
|
||||
.setContentIntent(openAppPending)
|
||||
.setAutoCancel(true)
|
||||
.setColor(ContextCompat.getColor(context, R.color.colorAccent))
|
||||
|
||||
notification.setSmallIcon(if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) R.drawable.ic_avh else R.drawable.ic_avhlogo)
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
val sound = if ((prefs.getString("ringtoneUri", "") ?: "").isNotEmpty()) {
|
||||
Uri.parse(prefs.getString("ringtoneUri", "") ?: "")
|
||||
|
||||
@@ -20,7 +20,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.checkSelfPermission
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.denizd.substitutionplan.R
|
||||
import com.denizd.substitutionplan.models.Subst
|
||||
import com.denizd.substitutionplan.models.Substitution
|
||||
import java.util.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@@ -45,6 +45,12 @@ internal object HelperFunctions {
|
||||
"brown", "grey", "pureWhite", "salmon", "tangerine", "banana", "flora", "spindrift", "sky", "orchid",
|
||||
"lavender", "carnation", "brown2", "pureBlack")
|
||||
|
||||
/**
|
||||
* A list of all phrases used to describe that a course has been cancelled. Expand this
|
||||
* if necessary. No further code changes required if this is expanded
|
||||
*/
|
||||
val cancellations = arrayOf("eigenverantwortliches arbeiten", "entfall", "entfällt", "fällt aus", "freisetzung", "vtr. ohne lehrer")
|
||||
|
||||
private val colourIntegers = intArrayOf(
|
||||
0,
|
||||
R.color.bgRed,
|
||||
@@ -135,6 +141,60 @@ internal object HelperFunctions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns a string that is used to get the colour set for a specific course
|
||||
* from Shared Preferences
|
||||
*
|
||||
* @param course the course abbreviation as a string
|
||||
*
|
||||
* @return the string used to store the course's colour in Shared Preferences
|
||||
*/
|
||||
fun getColourString(course: String): String {
|
||||
var colorCheck: String
|
||||
return try {
|
||||
colorCheck = course.toLowerCase(Locale.ROOT).substring(0, 3)
|
||||
when (colorCheck) {
|
||||
"deu", "dep", "daz", "fda" -> "German"
|
||||
"mat", "map" -> "Maths"
|
||||
"eng", "enp", "ena" -> "English"
|
||||
"spo", "spp", "spth" -> "PhysEd"
|
||||
"pol", "pop" -> "Politics"
|
||||
"dar", "dap" -> "Theatre"
|
||||
"phy", "php" -> "Physics"
|
||||
"bio", "bip", "nw1", "nw2", "nw3", "nw4" -> "Biology"
|
||||
"che", "chp" -> "Chemistry"
|
||||
"phi", "psp" -> "Philosophy"
|
||||
"laa", "laf", "lat" -> "Latin"
|
||||
"spa", "spf" -> "Spanish"
|
||||
"fra", "frf", "frz" -> "French"
|
||||
"inf" -> "CompSci"
|
||||
"ges" -> "History"
|
||||
"rel" -> "Religion"
|
||||
"geg" -> "Geography"
|
||||
"kun" -> "Arts"
|
||||
"mus" -> "Music"
|
||||
"tue" -> "Turkish"
|
||||
"chi" -> "Chinese"
|
||||
"gll" -> "GLL"
|
||||
"wat" -> "WAT"
|
||||
"för" -> "Forder"
|
||||
"met", "wpb" -> "WP"
|
||||
else -> ""
|
||||
}
|
||||
} catch (e: StringIndexOutOfBoundsException) {
|
||||
try {
|
||||
colorCheck = course.toLowerCase(Locale.ROOT).substring(0, 2)
|
||||
when (colorCheck) {
|
||||
"nw" -> "Biology"
|
||||
"wp" -> "WP"
|
||||
else -> ""
|
||||
}
|
||||
} catch (e2: StringIndexOutOfBoundsException) {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function served as a way to transfer a deprecated method of storing user-defined
|
||||
* course colours to a new method. It is not required otherwise, but still remains in
|
||||
@@ -163,17 +223,17 @@ internal object HelperFunctions {
|
||||
* This function serves for checking whether a course on the substitution plan is relevant to
|
||||
* the user and should be shown on their personal plan as well as in their notifications
|
||||
*
|
||||
* @param subst the substitution item
|
||||
* @param substitution the substitution item
|
||||
* @param coursePreference a string that represents the courses the user is enrolled in
|
||||
* @param classPreference a string that represents the group the user is in
|
||||
* @param psa decide whether or not any PSA items should be included in the filter
|
||||
*
|
||||
* @return true if the substitution is relevant to the user, false otherwise
|
||||
*/
|
||||
fun checkPersonalSubstitutions(subst: Subst, coursePreference: String, classPreference: String, psa: Boolean): Boolean {
|
||||
val group = subst.group
|
||||
val course = subst.course
|
||||
if (psa && subst.date.isNotEmpty() && subst.date.substring(0, 3) == "psa") {
|
||||
fun checkPersonalSubstitutions(substitution: Substitution, coursePreference: String, classPreference: String, psa: Boolean): Boolean {
|
||||
val group = substitution.group
|
||||
val course = substitution.course
|
||||
if (psa && substitution.date.isNotEmpty() && substitution.date.substring(0, 3) == "psa") {
|
||||
return true
|
||||
}
|
||||
if (coursePreference.isEmpty() && classPreference.isNotEmpty()) {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.denizd.substitutionplan.data
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.util.Log
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
/**
|
||||
* Class that extends WebViewClient to provide a function that checks the webpage's cookies to
|
||||
@@ -10,27 +13,40 @@ import android.webkit.WebViewClient
|
||||
*
|
||||
* @param successListener a reference to the OnLoginSuccessListener implemented in an activity
|
||||
*/
|
||||
internal class LoginWebViewClient(successListener: OnLoginSuccessListener) : WebViewClient() {
|
||||
internal class LoginWebViewClient(private val successListener: OnLoginSuccessListener) : WebViewClient() {
|
||||
|
||||
private val mSuccessListener = successListener
|
||||
/**
|
||||
* onPageStarted has been overridden to prevent users from reaching a domain different from
|
||||
* the school's login page
|
||||
*/
|
||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||
super.onPageStarted(view, url, favicon)
|
||||
|
||||
if (url != "https://307.joomla.schule.bremen.de/index.php/component/users/profile?Itemid=171"
|
||||
&& url != "https://307.joomla.schule.bremen.de/index.php/component/users/#top") {
|
||||
reloadLoginPage(webView = view)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OnPageFinished has been overridden to check if the cookie "joomla_user_state=logged_in"
|
||||
* exists, and returns true to the OnLoginSuccessListener
|
||||
*
|
||||
* @param view a reference to the WebView
|
||||
* @param url a reference to the url of the WebView
|
||||
*/
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
view?.scrollY = -4000
|
||||
view?.scrollY = -10_000
|
||||
|
||||
val cookies = CookieManager.getInstance().getCookie(url)
|
||||
|
||||
if (cookies.contains("joomla_user_state=logged_in")) {
|
||||
mSuccessListener.onLoginSucceeded(true)
|
||||
successListener.onLoginSucceeded(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadLoginPage(webView: WebView?) {
|
||||
webView?.loadUrl("https://307.joomla.schule.bremen.de/index.php/component/users/#top")
|
||||
}
|
||||
|
||||
/**
|
||||
* The interface that provides onLoginSucceeded to the activity or fragment that implements it
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user