QISPOSParser [Part 1]
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
* get the grades url from qispos
This commit is contained in:
parent
ea0caea91e
commit
ff0c4ad1a7
|
@ -63,6 +63,7 @@ dependencies {
|
||||||
implementation 'de.psdev.licensesdialog:licensesdialog:2.1.0'
|
implementation 'de.psdev.licensesdialog:licensesdialog:2.1.0'
|
||||||
|
|
||||||
implementation 'org.apache.commons:commons-lang3:3.10'
|
implementation 'org.apache.commons:commons-lang3:3.10'
|
||||||
|
implementation 'org.jsoup:jsoup:1.13.1'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13'
|
||||||
androidTestImplementation 'androidx.test:core:1.2.0'
|
androidTestImplementation 'androidx.test:core:1.2.0'
|
||||||
|
|
|
@ -43,12 +43,13 @@ import com.afollestad.aesthetic.NavigationViewMode
|
||||||
import com.google.android.material.navigation.NavigationView
|
import com.google.android.material.navigation.NavigationView
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.app_bar_main.*
|
import kotlinx.android.synthetic.main.app_bar_main.*
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.NFCMensaCard
|
import org.mosad.seil0.projectlaogai.controller.NFCMensaCard
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
|
import org.mosad.seil0.projectlaogai.controller.QISPOSParser
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
|
import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences
|
||||||
import org.mosad.seil0.projectlaogai.controller.login.LoginController
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cColorAccent
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cColorPrimary
|
||||||
import org.mosad.seil0.projectlaogai.fragments.*
|
import org.mosad.seil0.projectlaogai.fragments.*
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
@ -173,9 +174,13 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
*/
|
*/
|
||||||
private fun load() {
|
private fun load() {
|
||||||
val startupTime = measureTimeMillis {
|
val startupTime = measureTimeMillis {
|
||||||
PreferencesController.load(this) // load the settings, must be finished before doing anything else
|
Preferences.load(this) // load the settings, must be finished before doing anything else
|
||||||
CacheController(this) // load the cache
|
CacheController(this) // load the cache
|
||||||
LoginController.load(this)
|
EncryptedPreferences.load(this)
|
||||||
|
|
||||||
|
val parser = QISPOSParser()
|
||||||
|
parser.test(applicationContext)
|
||||||
|
|
||||||
}
|
}
|
||||||
Log.i(className, "startup completed in $startupTime ms")
|
Log.i(className, "startup completed in $startupTime ms")
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import com.codebutler.farebot.card.desfire.DesfireFileSettings
|
||||||
import com.codebutler.farebot.card.desfire.DesfireProtocol
|
import com.codebutler.farebot.card.desfire.DesfireProtocol
|
||||||
import kotlinx.android.synthetic.main.dialog_mensa_credit.*
|
import kotlinx.android.synthetic.main.dialog_mensa_credit.*
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.R
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
class NFCMensaCard {
|
class NFCMensaCard {
|
||||||
|
@ -84,13 +85,13 @@ class NFCMensaCard {
|
||||||
val dialog = MaterialDialog(context)
|
val dialog = MaterialDialog(context)
|
||||||
.customView(R.layout.dialog_mensa_credit)
|
.customView(R.layout.dialog_mensa_credit)
|
||||||
|
|
||||||
val current = if (!PreferencesController.oGiants) {
|
val current = if (!Preferences.oGiants) {
|
||||||
String.format("%.2f €", (currentRaw.toFloat() / 1000))
|
String.format("%.2f €", (currentRaw.toFloat() / 1000))
|
||||||
} else {
|
} else {
|
||||||
String.format("%.4f shm", (currentRaw.toFloat() * 0.0000075))
|
String.format("%.4f shm", (currentRaw.toFloat() * 0.0000075))
|
||||||
}
|
}
|
||||||
|
|
||||||
val last = if (!PreferencesController.oGiants) {
|
val last = if (!Preferences.oGiants) {
|
||||||
String.format("%.2f €", (lastRaw.toFloat() / 1000))
|
String.format("%.2f €", (lastRaw.toFloat() / 1000))
|
||||||
} else {
|
} else {
|
||||||
String.format("%.4f shm", (lastRaw.toFloat() * 0.0000075))
|
String.format("%.4f shm", (lastRaw.toFloat() * 0.0000075))
|
||||||
|
|
|
@ -1,189 +0,0 @@
|
||||||
/**
|
|
||||||
* ProjectLaogai
|
|
||||||
*
|
|
||||||
* Copyright 2019-2020 <seil0@mosad.xyz>
|
|
||||||
*
|
|
||||||
* 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, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.mosad.seil0.projectlaogai.controller
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Color
|
|
||||||
import org.mosad.seil0.projectlaogai.R
|
|
||||||
import org.mosad.seil0.projectlaogai.util.Course
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The PreferencesController class
|
|
||||||
* contains all preferences and global variables that exist in this app
|
|
||||||
*/
|
|
||||||
class PreferencesController {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
var coursesCacheTime: Long = 0
|
|
||||||
var mensaCacheTime: Long = 0
|
|
||||||
var timetableCacheTime: Long = 0
|
|
||||||
var cColorPrimary: Int = Color.parseColor("#009688")
|
|
||||||
var cColorAccent: Int = Color.parseColor("#0096ff")
|
|
||||||
var cCourse = Course(
|
|
||||||
"https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0",
|
|
||||||
"AI3"
|
|
||||||
)
|
|
||||||
var cShowBuffet = true
|
|
||||||
var oGiants = false
|
|
||||||
|
|
||||||
// the save function
|
|
||||||
fun save(context: Context) {
|
|
||||||
val sharedPref = context.getSharedPreferences(
|
|
||||||
context.getString(R.string.preference_file_key),
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
// save the update times (cache)
|
|
||||||
with (sharedPref.edit()) {
|
|
||||||
putLong(context.getString(R.string.save_key_coursesCacheTime),
|
|
||||||
coursesCacheTime
|
|
||||||
)
|
|
||||||
putLong(context.getString(R.string.save_key_mensaCacheTime),
|
|
||||||
mensaCacheTime
|
|
||||||
)
|
|
||||||
putLong(context.getString(R.string.save_key_timetableCacheTime),
|
|
||||||
timetableCacheTime
|
|
||||||
)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* save the course locally
|
|
||||||
*/
|
|
||||||
fun saveCourse(context: Context, course: Course) {
|
|
||||||
val sharedPref = context.getSharedPreferences(
|
|
||||||
context.getString(R.string.preference_file_key),
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
with (sharedPref.edit()) {
|
|
||||||
putString(context.getString(R.string.save_key_course), course.courseName)
|
|
||||||
putString(context.getString(R.string.save_key_courseTTLink), course.courseLink)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
cCourse = course
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* save the primary color
|
|
||||||
*/
|
|
||||||
fun saveColorPrimary(context: Context, colorPrimary: Int) {
|
|
||||||
val sharedPref = context.getSharedPreferences(
|
|
||||||
context.getString(R.string.preference_file_key),
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
with (sharedPref.edit()) {
|
|
||||||
putInt(context.getString(R.string.save_key_colorPrimary),
|
|
||||||
colorPrimary
|
|
||||||
)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
cColorPrimary = colorPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* save the accent color
|
|
||||||
*/
|
|
||||||
fun saveColorAccent(context: Context, colorAccent: Int) {
|
|
||||||
val sharedPref = context.getSharedPreferences(
|
|
||||||
context.getString(R.string.preference_file_key),
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
with (sharedPref.edit()) {
|
|
||||||
putInt(context.getString(R.string.save_key_colorAccent),
|
|
||||||
colorAccent
|
|
||||||
)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
cColorAccent = colorAccent
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* save showBuffet
|
|
||||||
*/
|
|
||||||
fun saveShowBuffet(context: Context, showBuffet: Boolean) {
|
|
||||||
val sharedPref = context.getSharedPreferences(
|
|
||||||
context.getString(R.string.preference_file_key),
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
with (sharedPref.edit()) {
|
|
||||||
putBoolean(context.getString(R.string.save_key_showBuffet),
|
|
||||||
showBuffet
|
|
||||||
)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
cShowBuffet = showBuffet
|
|
||||||
}
|
|
||||||
|
|
||||||
// the load function
|
|
||||||
fun load(context: Context) {
|
|
||||||
val sharedPref = context.getSharedPreferences(
|
|
||||||
context.getString(R.string.preference_file_key),
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
// load the update times (cache)
|
|
||||||
coursesCacheTime = sharedPref.getLong(context.getString(
|
|
||||||
R.string.save_key_coursesCacheTime
|
|
||||||
), 0)
|
|
||||||
mensaCacheTime = sharedPref.getLong(context.getString(
|
|
||||||
R.string.save_key_mensaCacheTime
|
|
||||||
), 0)
|
|
||||||
timetableCacheTime = sharedPref.getLong(context.getString(
|
|
||||||
R.string.save_key_timetableCacheTime
|
|
||||||
), 0)
|
|
||||||
|
|
||||||
// load saved course
|
|
||||||
cCourse = Course(
|
|
||||||
sharedPref.getString(
|
|
||||||
context.getString(R.string.save_key_courseTTLink),
|
|
||||||
"https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0"
|
|
||||||
)!!,
|
|
||||||
sharedPref.getString(context.getString(R.string.save_key_course), "AI3")!!
|
|
||||||
)
|
|
||||||
|
|
||||||
// load saved colors
|
|
||||||
cColorPrimary = sharedPref.getInt(context.getString(
|
|
||||||
R.string.save_key_colorPrimary
|
|
||||||
), cColorPrimary)
|
|
||||||
cColorAccent = sharedPref.getInt(context.getString(
|
|
||||||
R.string.save_key_colorAccent
|
|
||||||
), cColorAccent)
|
|
||||||
|
|
||||||
// load showBuffet
|
|
||||||
cShowBuffet = sharedPref.getBoolean(context.getString(
|
|
||||||
R.string.save_key_showBuffet
|
|
||||||
), true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
package org.mosad.seil0.projectlaogai.controller
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import org.mosad.seil0.projectlaogai.R
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences
|
||||||
|
import java.security.KeyStore
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.SSLSocketFactory
|
||||||
|
import javax.net.ssl.TrustManagerFactory
|
||||||
|
|
||||||
|
class QISPOSParser {
|
||||||
|
|
||||||
|
private val className = this.javaClass.name
|
||||||
|
private val baseURL = "https://notenverwaltung.hs-offenburg.de"
|
||||||
|
private val loginPath = "/qispos/rds?state=user&type=1&category=auth.login&startpage=portal.vm&breadCrumbSource=portal"
|
||||||
|
private val rootPath = "/qispos/rds?state=change&type=1&moduleParameter=studyPOSMenu&nextdir=change&next=menu.vm&subdir=applications&xml=menu&purge=y&navigationPosition=functions%2CstudyPOSMenu&breadcrumb=studyPOSMenu&topitem=functions&subitem=studyPOSMenu"
|
||||||
|
|
||||||
|
fun test(context: Context) {
|
||||||
|
|
||||||
|
val credentials = EncryptedPreferences.readCredentials(context)
|
||||||
|
val username = credentials.first.substringBefore("@")
|
||||||
|
val password = credentials.second
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
println("querying qispos ...")
|
||||||
|
println("using $username with ********")
|
||||||
|
|
||||||
|
val socketFactory = createSSLSocketFactory(context)
|
||||||
|
|
||||||
|
// login, asdf = username, fdsa = password, wtf
|
||||||
|
val list = mapOf(
|
||||||
|
Pair("asdf", username),
|
||||||
|
Pair("fdsa", password),
|
||||||
|
Pair("submit", "Anmelden")
|
||||||
|
)
|
||||||
|
|
||||||
|
// login and get session cookies
|
||||||
|
val res = Jsoup.connect(baseURL + loginPath)
|
||||||
|
.sslSocketFactory(socketFactory)
|
||||||
|
.followRedirects(true)
|
||||||
|
.referrer("https://notenverwaltung.hs-offenburg.de/qispos/rds?state=user&type=0")
|
||||||
|
.data(list)
|
||||||
|
.postDataCharset("UTF-8")
|
||||||
|
.execute()
|
||||||
|
|
||||||
|
val loginCookies = res.cookies()
|
||||||
|
|
||||||
|
println("cookies: $loginCookies")
|
||||||
|
println("status is: ${res.statusMessage()}: ${res.statusCode()}")
|
||||||
|
println(res.body())
|
||||||
|
|
||||||
|
// grades url
|
||||||
|
val test = Jsoup.parse(res.body()).select("li.menueListStyle").select("a.auflistung").last()
|
||||||
|
println(test)
|
||||||
|
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Log.e(className, "could not load qispos", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSSLSocketFactory(context: Context): SSLSocketFactory {
|
||||||
|
// Load CAs from an InputStream
|
||||||
|
// (could be from a resource or ByteArrayInputStream or ...)
|
||||||
|
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
|
||||||
|
val caInput = context.resources.openRawResource(R.raw.notenverwaltung_hs_offenburg_de)
|
||||||
|
val ca = caInput.use {
|
||||||
|
cf.generateCertificate(it) as X509Certificate
|
||||||
|
}
|
||||||
|
println("ca=" + ca.subjectDN)
|
||||||
|
|
||||||
|
// Create a KeyStore containing our trusted CAs
|
||||||
|
val keyStoreType = KeyStore.getDefaultType()
|
||||||
|
val keyStore = KeyStore.getInstance(keyStoreType).apply {
|
||||||
|
load(null, null)
|
||||||
|
setCertificateEntry("ca", ca)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a TrustManager that trusts the CAs inputStream our KeyStore
|
||||||
|
val tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm()
|
||||||
|
val tmf = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
|
||||||
|
init(keyStore)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an SSLContext that uses our TrustManager
|
||||||
|
val sslContext = SSLContext.getInstance("TLS").apply {
|
||||||
|
init(null, tmf.trustManagers, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sslContext.socketFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -29,12 +29,12 @@ import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.coursesCacheTime
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.mensaCacheTime
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.timetableCacheTime
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cCourse
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.coursesCacheTime
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.mensaCacheTime
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.timetableCacheTime
|
||||||
import org.mosad.seil0.projectlaogai.util.*
|
import org.mosad.seil0.projectlaogai.util.*
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -122,7 +122,7 @@ class CacheController(cont: Context) {
|
||||||
// save cache file and update time
|
// save cache file and update time
|
||||||
save(file, Gson().toJson(courseListUp))
|
save(file, Gson().toJson(courseListUp))
|
||||||
coursesCacheTime = System.currentTimeMillis() / 1000
|
coursesCacheTime = System.currentTimeMillis() / 1000
|
||||||
PreferencesController.save(context)
|
Preferences.save(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ class CacheController(cont: Context) {
|
||||||
// save cache file and update time
|
// save cache file and update time
|
||||||
save(file, Gson().toJson(mensaMenu))
|
save(file, Gson().toJson(mensaMenu))
|
||||||
mensaCacheTime = System.currentTimeMillis() / 1000
|
mensaCacheTime = System.currentTimeMillis() / 1000
|
||||||
PreferencesController.save(context)
|
Preferences.save(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ class CacheController(cont: Context) {
|
||||||
// save cache file and update time
|
// save cache file and update time
|
||||||
save(file, Gson().toJson(timetable))
|
save(file, Gson().toJson(timetable))
|
||||||
timetableCacheTime = System.currentTimeMillis() / 1000
|
timetableCacheTime = System.currentTimeMillis() / 1000
|
||||||
PreferencesController.save(context)
|
Preferences.save(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ package org.mosad.seil0.projectlaogai.controller.cache
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cCourse
|
||||||
import org.mosad.seil0.projectlaogai.util.Lesson
|
import org.mosad.seil0.projectlaogai.util.Lesson
|
||||||
import org.mosad.seil0.projectlaogai.util.TimetableWeek
|
import org.mosad.seil0.projectlaogai.util.TimetableWeek
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.mosad.seil0.projectlaogai.controller.login
|
package org.mosad.seil0.projectlaogai.controller.preferences
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
@ -31,23 +31,11 @@ import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
import androidx.security.crypto.MasterKey
|
import androidx.security.crypto.MasterKey
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.R
|
||||||
|
|
||||||
object LoginController {
|
object EncryptedPreferences {
|
||||||
|
|
||||||
var email = ""
|
var email = ""
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
/**
|
|
||||||
* initially load the users email
|
|
||||||
*/
|
|
||||||
fun load(context: Context) {
|
|
||||||
with(getEncryptedPreferences(context)) {
|
|
||||||
email = this?.getString(
|
|
||||||
context.getString(R.string.save_key_user_email),
|
|
||||||
context.getString(R.string.sample_user)
|
|
||||||
).toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* save user email and password to encrypted preference
|
* save user email and password to encrypted preference
|
||||||
*/
|
*/
|
||||||
|
@ -64,6 +52,7 @@ object LoginController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read user email and password from encrypted preference
|
* read user email and password from encrypted preference
|
||||||
|
* @return Pair(email, password)
|
||||||
*/
|
*/
|
||||||
fun readCredentials(context: Context): Pair<String, String> {
|
fun readCredentials(context: Context): Pair<String, String> {
|
||||||
return with (getEncryptedPreferences(context)) {
|
return with (getEncryptedPreferences(context)) {
|
||||||
|
@ -76,6 +65,18 @@ object LoginController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initially load the stored values
|
||||||
|
*/
|
||||||
|
fun load(context: Context) {
|
||||||
|
with(getEncryptedPreferences(context)) {
|
||||||
|
email = this?.getString(
|
||||||
|
context.getString(R.string.save_key_user_email),
|
||||||
|
context.getString(R.string.sample_user)
|
||||||
|
).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a encrypted shared preference
|
* create a encrypted shared preference
|
||||||
*/
|
*/
|
|
@ -0,0 +1,188 @@
|
||||||
|
/**
|
||||||
|
* ProjectLaogai
|
||||||
|
*
|
||||||
|
* Copyright 2019-2020 <seil0@mosad.xyz>
|
||||||
|
*
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.mosad.seil0.projectlaogai.controller.preferences
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import org.mosad.seil0.projectlaogai.R
|
||||||
|
import org.mosad.seil0.projectlaogai.util.Course
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PreferencesController class
|
||||||
|
* contains all preferences and global variables that exist in this app
|
||||||
|
*/
|
||||||
|
object Preferences {
|
||||||
|
|
||||||
|
var coursesCacheTime: Long = 0
|
||||||
|
var mensaCacheTime: Long = 0
|
||||||
|
var timetableCacheTime: Long = 0
|
||||||
|
var cColorPrimary: Int = Color.parseColor("#009688")
|
||||||
|
var cColorAccent: Int = Color.parseColor("#0096ff")
|
||||||
|
var cCourse = Course(
|
||||||
|
"https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0",
|
||||||
|
"AI3"
|
||||||
|
)
|
||||||
|
var cShowBuffet = true
|
||||||
|
var oGiants = false
|
||||||
|
|
||||||
|
// the save function
|
||||||
|
fun save(context: Context) {
|
||||||
|
val sharedPref = context.getSharedPreferences(
|
||||||
|
context.getString(R.string.preference_file_key),
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
// save the update times (cache)
|
||||||
|
with (sharedPref.edit()) {
|
||||||
|
putLong(context.getString(R.string.save_key_coursesCacheTime),
|
||||||
|
coursesCacheTime
|
||||||
|
)
|
||||||
|
putLong(context.getString(R.string.save_key_mensaCacheTime),
|
||||||
|
mensaCacheTime
|
||||||
|
)
|
||||||
|
putLong(context.getString(R.string.save_key_timetableCacheTime),
|
||||||
|
timetableCacheTime
|
||||||
|
)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save the course locally
|
||||||
|
*/
|
||||||
|
fun saveCourse(context: Context, course: Course) {
|
||||||
|
val sharedPref = context.getSharedPreferences(
|
||||||
|
context.getString(R.string.preference_file_key),
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
with (sharedPref.edit()) {
|
||||||
|
putString(context.getString(R.string.save_key_course), course.courseName)
|
||||||
|
putString(context.getString(R.string.save_key_courseTTLink), course.courseLink)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
cCourse = course
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save the primary color
|
||||||
|
*/
|
||||||
|
fun saveColorPrimary(context: Context, colorPrimary: Int) {
|
||||||
|
val sharedPref = context.getSharedPreferences(
|
||||||
|
context.getString(R.string.preference_file_key),
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
with (sharedPref.edit()) {
|
||||||
|
putInt(context.getString(R.string.save_key_colorPrimary),
|
||||||
|
colorPrimary
|
||||||
|
)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
cColorPrimary = colorPrimary
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save the accent color
|
||||||
|
*/
|
||||||
|
fun saveColorAccent(context: Context, colorAccent: Int) {
|
||||||
|
val sharedPref = context.getSharedPreferences(
|
||||||
|
context.getString(R.string.preference_file_key),
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
with (sharedPref.edit()) {
|
||||||
|
putInt(context.getString(R.string.save_key_colorAccent),
|
||||||
|
colorAccent
|
||||||
|
)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
cColorAccent = colorAccent
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save showBuffet
|
||||||
|
*/
|
||||||
|
fun saveShowBuffet(context: Context, showBuffet: Boolean) {
|
||||||
|
val sharedPref = context.getSharedPreferences(
|
||||||
|
context.getString(R.string.preference_file_key),
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
with (sharedPref.edit()) {
|
||||||
|
putBoolean(context.getString(R.string.save_key_showBuffet),
|
||||||
|
showBuffet
|
||||||
|
)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
cShowBuffet = showBuffet
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initially load the stored values
|
||||||
|
*/
|
||||||
|
fun load(context: Context) {
|
||||||
|
val sharedPref = context.getSharedPreferences(
|
||||||
|
context.getString(R.string.preference_file_key),
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
// load the update times (cache)
|
||||||
|
coursesCacheTime = sharedPref.getLong(context.getString(
|
||||||
|
R.string.save_key_coursesCacheTime
|
||||||
|
), 0)
|
||||||
|
mensaCacheTime = sharedPref.getLong(context.getString(
|
||||||
|
R.string.save_key_mensaCacheTime
|
||||||
|
), 0)
|
||||||
|
timetableCacheTime = sharedPref.getLong(context.getString(
|
||||||
|
R.string.save_key_timetableCacheTime
|
||||||
|
), 0)
|
||||||
|
|
||||||
|
// load saved course
|
||||||
|
cCourse = Course(
|
||||||
|
sharedPref.getString(context.getString(R.string.save_key_courseTTLink),
|
||||||
|
"https://www.hs-offenburg.de/index.php?id=6627&class=class&iddV=DA64F6FE-9DDB-429E-A677-05D0D40CB636&week=0"
|
||||||
|
)!!,
|
||||||
|
sharedPref.getString(context.getString(R.string.save_key_course), "AI3")!!
|
||||||
|
)
|
||||||
|
|
||||||
|
// load saved colors
|
||||||
|
cColorPrimary = sharedPref.getInt(context.getString(
|
||||||
|
R.string.save_key_colorPrimary
|
||||||
|
), cColorPrimary)
|
||||||
|
cColorAccent = sharedPref.getInt(context.getString(
|
||||||
|
R.string.save_key_colorAccent
|
||||||
|
), cColorAccent)
|
||||||
|
|
||||||
|
// load showBuffet
|
||||||
|
cShowBuffet = sharedPref.getBoolean(context.getString(
|
||||||
|
R.string.save_key_showBuffet
|
||||||
|
), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ import kotlinx.coroutines.withContext
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.R
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.CacheController.Companion.mensaMenu
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController.Companion.mensaMenu
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cShowBuffet
|
||||||
import org.mosad.seil0.projectlaogai.util.MensaWeek
|
import org.mosad.seil0.projectlaogai.util.MensaWeek
|
||||||
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
|
import org.mosad.seil0.projectlaogai.uicomponents.DayCardView
|
||||||
import org.mosad.seil0.projectlaogai.uicomponents.MealLinearLayout
|
import org.mosad.seil0.projectlaogai.uicomponents.MealLinearLayout
|
||||||
|
|
|
@ -49,13 +49,13 @@ import org.mosad.seil0.projectlaogai.BuildConfig
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.R
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.CacheController.Companion.coursesList
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController.Companion.coursesList
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorAccent
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cColorPrimary
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cCourse
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController.Companion.cShowBuffet
|
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.TimetableController
|
import org.mosad.seil0.projectlaogai.controller.cache.TimetableController
|
||||||
import org.mosad.seil0.projectlaogai.controller.login.LoginController
|
import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cColorAccent
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cColorPrimary
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cCourse
|
||||||
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences.cShowBuffet
|
||||||
import org.mosad.seil0.projectlaogai.uicomponents.dialogs.LoginDialog
|
import org.mosad.seil0.projectlaogai.uicomponents.dialogs.LoginDialog
|
||||||
import org.mosad.seil0.projectlaogai.util.DataTypes
|
import org.mosad.seil0.projectlaogai.util.DataTypes
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -105,7 +105,7 @@ class SettingsFragment : Fragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
// initialize the settings gui
|
// initialize the settings gui
|
||||||
txtView_User.text = LoginController.email
|
txtView_User.text = EncryptedPreferences.email
|
||||||
txtView_Course.text = cCourse.courseName
|
txtView_Course.text = cCourse.courseName
|
||||||
txtView_AboutDesc.text = resources.getString(R.string.about_version, BuildConfig.VERSION_NAME, getString(R.string.build_time))
|
txtView_AboutDesc.text = resources.getString(R.string.about_version, BuildConfig.VERSION_NAME, getString(R.string.build_time))
|
||||||
switch_buffet.isChecked = cShowBuffet // init switch
|
switch_buffet.isChecked = cShowBuffet // init switch
|
||||||
|
@ -141,16 +141,16 @@ class SettingsFragment : Fragment() {
|
||||||
LoginDialog(context!!)
|
LoginDialog(context!!)
|
||||||
.positiveButton {
|
.positiveButton {
|
||||||
println("Test: $password")
|
println("Test: $password")
|
||||||
LoginController.saveCredentials(email, password, context)
|
EncryptedPreferences.saveCredentials(email, password, context)
|
||||||
}
|
}
|
||||||
.show {
|
.show {
|
||||||
email = LoginController.email
|
email = EncryptedPreferences.email
|
||||||
password = ""
|
password = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
linLayoutUser.setOnLongClickListener {
|
linLayoutUser.setOnLongClickListener {
|
||||||
PreferencesController.oGiants = true // enable easter egg
|
Preferences.oGiants = true // enable easter egg
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,6 @@ class SettingsFragment : Fragment() {
|
||||||
items.forEach {
|
items.forEach {
|
||||||
val list = it.split(" - ")
|
val list = it.split(" - ")
|
||||||
TimetableController.removeSubject(list[0], list[1], context)
|
TimetableController.removeSubject(list[0], list[1], context)
|
||||||
// TODO save
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +253,7 @@ class SettingsFragment : Fragment() {
|
||||||
colorPrimaryDark(color)
|
colorPrimaryDark(color)
|
||||||
apply()
|
apply()
|
||||||
}
|
}
|
||||||
PreferencesController.saveColorPrimary(context!!, color)
|
Preferences.saveColorPrimary(context!!, color)
|
||||||
}
|
}
|
||||||
.show {
|
.show {
|
||||||
title(R.string.primary_color)
|
title(R.string.primary_color)
|
||||||
|
@ -274,7 +273,7 @@ class SettingsFragment : Fragment() {
|
||||||
apply()
|
apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferencesController.saveColorAccent(context!!, color)
|
Preferences.saveColorAccent(context!!, color)
|
||||||
}
|
}
|
||||||
.show{
|
.show{
|
||||||
title(R.string.accent_color)
|
title(R.string.accent_color)
|
||||||
|
@ -284,7 +283,7 @@ class SettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
switchBuffet.setOnClickListener {
|
switchBuffet.setOnClickListener {
|
||||||
PreferencesController.saveShowBuffet(context!!, switchBuffet.isChecked)
|
Preferences.saveShowBuffet(context!!, switchBuffet.isChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -306,7 +305,7 @@ class SettingsFragment : Fragment() {
|
||||||
loadingDialog.show()
|
loadingDialog.show()
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
PreferencesController.saveCourse(context, coursesList[index]) // save the course
|
Preferences.saveCourse(context, coursesList[index]) // save the course
|
||||||
|
|
||||||
// update current & next weeks timetable
|
// update current & next weeks timetable
|
||||||
val threads = listOf(
|
val threads = listOf(
|
||||||
|
|
|
@ -37,7 +37,7 @@ import com.afollestad.materialdialogs.customview.customView
|
||||||
import com.afollestad.materialdialogs.customview.getCustomView
|
import com.afollestad.materialdialogs.customview.getCustomView
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.R
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
||||||
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
import org.mosad.seil0.projectlaogai.controller.cache.CacheController
|
||||||
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
import org.mosad.seil0.projectlaogai.controller.TCoRAPIController
|
||||||
import org.mosad.seil0.projectlaogai.util.Course
|
import org.mosad.seil0.projectlaogai.util.Course
|
||||||
|
@ -71,8 +71,8 @@ class AddSubjectDialog(val context: Context) {
|
||||||
spinnerSubjects = dialog.getCustomView().findViewById(R.id.spinner_Lessons)
|
spinnerSubjects = dialog.getCustomView().findViewById(R.id.spinner_Lessons)
|
||||||
|
|
||||||
// fix not working accent color
|
// fix not working accent color
|
||||||
dialog.getActionButton(WhichButton.POSITIVE).updateTextColor(PreferencesController.cColorAccent)
|
dialog.getActionButton(WhichButton.POSITIVE).updateTextColor(Preferences.cColorAccent)
|
||||||
dialog.getActionButton(WhichButton.NEGATIVE).updateTextColor(PreferencesController.cColorAccent)
|
dialog.getActionButton(WhichButton.NEGATIVE).updateTextColor(Preferences.cColorAccent)
|
||||||
|
|
||||||
initSpinners()
|
initSpinners()
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import com.afollestad.materialdialogs.bottomsheets.setPeekHeight
|
||||||
import com.afollestad.materialdialogs.customview.customView
|
import com.afollestad.materialdialogs.customview.customView
|
||||||
import com.afollestad.materialdialogs.customview.getCustomView
|
import com.afollestad.materialdialogs.customview.getCustomView
|
||||||
import org.mosad.seil0.projectlaogai.R
|
import org.mosad.seil0.projectlaogai.R
|
||||||
import org.mosad.seil0.projectlaogai.controller.PreferencesController
|
import org.mosad.seil0.projectlaogai.controller.preferences.Preferences
|
||||||
|
|
||||||
class LoginDialog(val context: Context) {
|
class LoginDialog(val context: Context) {
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ class LoginDialog(val context: Context) {
|
||||||
editTextPassword = dialog.getCustomView().findViewById(R.id.editText_password)
|
editTextPassword = dialog.getCustomView().findViewById(R.id.editText_password)
|
||||||
|
|
||||||
// fix not working accent color
|
// fix not working accent color
|
||||||
dialog.getActionButton(WhichButton.POSITIVE).updateTextColor(PreferencesController.cColorAccent)
|
dialog.getActionButton(WhichButton.POSITIVE).updateTextColor(Preferences.cColorAccent)
|
||||||
dialog.getActionButton(WhichButton.NEGATIVE).updateTextColor(PreferencesController.cColorAccent)
|
dialog.getActionButton(WhichButton.NEGATIVE).updateTextColor(Preferences.cColorAccent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun positiveButton(func: LoginDialog.() -> Unit): LoginDialog = apply {
|
fun positiveButton(func: LoginDialog.() -> Unit): LoginDialog = apply {
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue