diff --git a/app/build.gradle b/app/build.gradle index b05d11ce..70a7de7f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -160,6 +160,8 @@ dependencies { //implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1' implementation "org.redundent:kotlin-xml-builder:1.5.3" + + implementation "io.github.wulkanowy:signer-android:0.1.0" } repositories { mavenCentral() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/VulcanApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/VulcanApi.kt index f54cfdd3..b9ebda85 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/VulcanApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/VulcanApi.kt @@ -4,17 +4,18 @@ package pl.szczodrzynski.edziennik.api.v2.vulcan.data +import com.google.gson.JsonArray import com.google.gson.JsonObject import im.wangchao.mhttp.Request import im.wangchao.mhttp.Response import im.wangchao.mhttp.callback.JsonCallbackHandler +import io.github.wulkanowy.signer.android.signContent import pl.szczodrzynski.edziennik.api.v2.* import pl.szczodrzynski.edziennik.api.v2.models.ApiError import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan import pl.szczodrzynski.edziennik.data.db.modules.teams.Team import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils.d -import pl.szczodrzynski.edziennik.utils.models.Date import java.net.HttpURLConnection import java.util.* @@ -26,17 +27,20 @@ open class VulcanApi(open val data: DataVulcan) { val profileId get() = data.profile?.id ?: -1 - val profile - get() = data.profile - - fun apiGet(tag: String, endpoint: String, method: Int = POST, payload: JsonObject? = null, - baseUrl: Boolean = false, onSuccess: (json: JsonObject, response: Response?) -> Unit) { - val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}$endpoint" + fun apiGet( + tag: String, + endpoint: String, + method: Int = POST, + parameters: Map = emptyMap(), + baseUrl: Boolean = false, + onSuccess: (json: JsonObject, response: Response?) -> Unit + ) { + val url = "${if (baseUrl) data.apiUrl else data.fullApiUrl}/$endpoint" d(tag, "Request: Vulcan/Api - $url") if (data.teamList.size() == 0) { - profile?.getStudentData("studentClassName", null)?.also { name -> + data.profile?.getStudentData("studentClassName", null)?.also { name -> val id = Utils.crc16(name.toByteArray()).toLong() val teamObject = Team( @@ -51,28 +55,24 @@ open class VulcanApi(open val data: DataVulcan) { } } - val startDate = when (profile?.empty) { - true -> profile?.getSemesterStart(profile?.currentSemester ?: 1)?.stringY_m_d - else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d - } - val endDate = profile?.getSemesterEnd(profile?.currentSemester ?: 1)?.stringY_m_d - val finalPayload = JsonObject() - finalPayload.addProperty("IdUczen", data.studentId) - finalPayload.addProperty("IdOkresKlasyfikacyjny", data.studentSemesterId) - finalPayload.addProperty("IdOddzial", data.studentClassId) - finalPayload.addProperty("DataPoczatkowa", startDate) - finalPayload.addProperty("DataKoncowa", endDate) + parameters.map { (name, value) -> + when (value) { + is JsonObject -> finalPayload.add(name, value) + is JsonArray -> finalPayload.add(name, value) + is String -> finalPayload.addProperty(name, value) + is Int -> finalPayload.addProperty(name, value) + is Long -> finalPayload.addProperty(name, value) + is Float -> finalPayload.addProperty(name, value) + is Char -> finalPayload.addProperty(name, value) + } + } finalPayload.addProperty("RemoteMobileTimeKey", System.currentTimeMillis() / 1000) finalPayload.addProperty("TimeKey", System.currentTimeMillis() / 1000 - 1) finalPayload.addProperty("RequestId", UUID.randomUUID().toString()) finalPayload.addProperty("RemoteMobileAppVersion", VULCAN_API_APP_VERSION) finalPayload.addProperty("RemoteMobileAppName", VULCAN_API_APP_NAME) - payload?.keySet()?.forEach { - finalPayload.add(it, payload.get(it)) - } - val callback = object : JsonCallbackHandler() { override fun onSuccess(json: JsonObject?, response: Response?) { if (json == null && response?.parserErrorBody == null) { @@ -86,10 +86,11 @@ open class VulcanApi(open val data: DataVulcan) { 503 -> ERROR_VULCAN_API_MAINTENANCE 400 -> ERROR_VULCAN_API_BAD_REQUEST else -> ERROR_VULCAN_API_OTHER - }.let { - data.error(ApiError(tag, EXCEPTION_VULCAN_API_REQUEST) + }.let { errorCode -> + data.error(ApiError(tag, errorCode) .withResponse(response) .withApiResponse(json?.toString() ?: response?.parserErrorBody)) + return } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/signer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/signer.kt deleted file mode 100644 index 5f0447d8..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/data/signer.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Wulkanowy kiedyƛ tam. - */ - -package pl.szczodrzynski.edziennik.api.v2.vulcan.data - -import android.util.Base64 -import java.io.ByteArrayInputStream -import java.security.KeyFactory -import java.security.KeyStore -import java.security.PrivateKey -import java.security.Signature -import java.security.spec.PKCS8EncodedKeySpec - -fun signContent(password: String, certificate: String?, content: String): String { - val keystore = KeyStore.getInstance("pkcs12").apply { - load(ByteArrayInputStream(Base64.decode(certificate, Base64.DEFAULT)), password.toCharArray()) - } - val signature = Signature.getInstance("SHA1WithRSA").apply { - initSign(keystore.getKey("LoginCert", password.toCharArray()) as PrivateKey) - update(content.toByteArray()) - } - return Base64.encodeToString(signature.sign(), Base64.NO_WRAP) -} - -fun signContent(privateKey: String, content: String): String { - val key = PKCS8EncodedKeySpec(Base64.decode(privateKey, Base64.DEFAULT)).let { - KeyFactory.getInstance("RSA").generatePrivate(it) - } - val signature = Signature.getInstance("SHA1WithRSA").apply { - initSign(key) - update(content.toByteArray()) - } - return Base64.encodeToString(signature.sign(), Base64.NO_WRAP) -} - -fun getPrivateKeyFromCert(password: String, certificate: String): String { - val keystore = KeyStore.getInstance("pkcs12").apply { - load(ByteArrayInputStream(Base64.decode(certificate, Base64.DEFAULT)), password.toCharArray()) - } - val keyFactory = KeyFactory.getInstance("RSA") - val keySpec = keyFactory.getKeySpec( - keystore.getKey("LoginCert", password.toCharArray()) as PrivateKey, - PKCS8EncodedKeySpec::class.java - ) - return Base64.encodeToString(keySpec.encoded, Base64.NO_WRAP) -} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/login/VulcanLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/login/VulcanLoginApi.kt index ed42277d..ee81cb9e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/login/VulcanLoginApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/vulcan/login/VulcanLoginApi.kt @@ -9,10 +9,10 @@ import com.google.gson.JsonObject import im.wangchao.mhttp.Request import im.wangchao.mhttp.Response import im.wangchao.mhttp.callback.JsonCallbackHandler +import io.github.wulkanowy.signer.android.getPrivateKeyFromCert import pl.szczodrzynski.edziennik.api.v2.* import pl.szczodrzynski.edziennik.api.v2.models.ApiError import pl.szczodrzynski.edziennik.api.v2.vulcan.DataVulcan -import pl.szczodrzynski.edziennik.api.v2.vulcan.data.getPrivateKeyFromCert import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.getJsonObject import pl.szczodrzynski.edziennik.getString diff --git a/build.gradle b/build.gradle index 2e2db165..5e08c012 100644 --- a/build.gradle +++ b/build.gradle @@ -81,6 +81,7 @@ allprojects { jcenter() maven { url 'https://jitpack.io' } maven { url "https://kotlin.bintray.com/kotlinx/" } + maven { url "https://dl.bintray.com/wulkanowy/wulkanowy" } } }