Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f382eeb4fe | ||
|
|
11d7ed1fa6 |
No files matched your search
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## v0.1.10 – 2026-10-25
|
||||
|
||||
- 🐛 **Corrigé** — Configuration Firebase (Réglages → Contrôle parental) : le bloc collé est accepté même si le copier-coller a remplacé les guillemets par des guillemets typographiques (“ ” « »), et le contenu du fichier google-services.json de l'application Android est aussi reconnu.
|
||||
|
||||
## v0.1.9 – 2026-10-25
|
||||
|
||||
- 🔒 **Sécurité** — Retirer l'autorisation VPN ou activer un autre VPN ne désactive plus le contrôle : la notification passe en rouge, le parent est alerté, le tunnel est remonté après 30 s si possible et l'autorisation est redemandée à l'ouverture.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# DataControl
|
||||
|
||||
🚀 v0.1.9 · 🤖 Android · 🟣 Kotlin · 🎨 Jetpack Compose · 🔥 Firebase · 🔒 pare-feu VPN local · 👨👩👧 contrôle parental · 🧪 tests · 📄 licence non déclarée
|
||||
🚀 v0.1.10 · 🤖 Android · 🟣 Kotlin · 🎨 Jetpack Compose · 🔥 Firebase · 🔒 pare-feu VPN local · 👨👩👧 contrôle parental · 🧪 tests · 📄 licence non déclarée
|
||||
|
||||
**DataControl** est une application Android qui surveille en arrière-plan la consommation de données mobiles et coupe automatiquement l'accès à Internet en cas de dépassement du forfait — sans jamais toucher au Wi-Fi.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ data class FirebaseConfig(val apiKey: String, val appId: String, val projectId:
|
||||
companion object {
|
||||
/**
|
||||
* Lit ce que l'utilisateur colle : le bloc `firebaseConfig` de la console (JavaScript), un JSON,
|
||||
* ou une chaîne « fc1:… » partagée par FamilyControl. Renvoie null si apiKey, appId ou projectId manque.
|
||||
* le fichier google-services.json, ou une chaîne « fc1:… » partagée par FamilyControl. Renvoie null si apiKey, appId ou projectId manque.
|
||||
*/
|
||||
fun parse(input: String): FirebaseConfig? {
|
||||
val text = input.trim()
|
||||
@@ -17,9 +17,17 @@ data class FirebaseConfig(val apiKey: String, val appId: String, val projectId:
|
||||
build(json.optString("apiKey"), json.optString("appId"), json.optString("projectId"))
|
||||
}.getOrNull()
|
||||
}
|
||||
fun pick(name: String) =
|
||||
Regex("""["']?$name["']?\s*[:=]\s*["']([^"']+)["']""").find(text)?.groupValues?.get(1)
|
||||
return build(pick("apiKey"), pick("appId"), pick("projectId"))
|
||||
// Guillemets typographiques (souvent insérés par un copier-coller sur téléphone) → droits.
|
||||
val plain = text.replace(Regex("[“”„«»]"), "\"").replace(Regex("[‘’]"), "'")
|
||||
// Noms du bloc Web (apiKey…) ou du fichier google-services.json de l'application Android.
|
||||
fun pick(vararg names: String) = names.firstNotNullOfOrNull { name ->
|
||||
Regex("""["']?\b$name["']?\s*[:=]\s*["']\s*([^"'\s]+)\s*["']""").find(plain)?.groupValues?.get(1)
|
||||
}
|
||||
return build(
|
||||
pick("apiKey", "current_key"),
|
||||
pick("appId", "mobilesdk_app_id"),
|
||||
pick("projectId", "project_id")
|
||||
)
|
||||
}
|
||||
|
||||
private fun build(apiKey: String?, appId: String?, projectId: String?): FirebaseConfig? =
|
||||
|
||||
@@ -35,6 +35,25 @@ class FirebaseConfigTest {
|
||||
assertEquals(expected, FirebaseConfig.parse(" fc1:${b64.chunked(20).joinToString("\n")} "))
|
||||
}
|
||||
|
||||
@Test fun `guillemets typographiques`() {
|
||||
val js = "apiKey: “AIzaTest”, projectId: «mon-projet», appId: ‘1:123:android:abc’"
|
||||
assertEquals(expected, FirebaseConfig.parse(js))
|
||||
}
|
||||
|
||||
@Test fun `fichier google-services json`() {
|
||||
val gs = """
|
||||
{
|
||||
"project_info": { "project_number": "123", "project_id": "mon-projet", "storage_bucket": "mon-projet.appspot.com" },
|
||||
"client": [ {
|
||||
"client_info": { "mobilesdk_app_id": "1:123:android:abc",
|
||||
"android_client_info": { "package_name": "com.jttools.datacontrol" } },
|
||||
"api_key": [ { "current_key": "AIzaTest" } ]
|
||||
} ]
|
||||
}
|
||||
""".trimIndent()
|
||||
assertEquals(expected, FirebaseConfig.parse(gs))
|
||||
}
|
||||
|
||||
@Test fun `champ manquant ou illisible`() {
|
||||
assertNull(FirebaseConfig.parse("""{"apiKey":"AIzaTest","projectId":"mon-projet"}"""))
|
||||
assertNull(FirebaseConfig.parse("fc1:!!!"))
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
versionName=0.1.9
|
||||
versionCode=10
|
||||
versionName=0.1.10
|
||||
versionCode=11
|
||||
Reference in new issue
Block a user