diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c1fe7d --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# Android Studio +.idea/ +*.iml +.gradle/ +build/ +captures/ + +# OS generated files +.DS_Store +Thumbs.db + +# Kotlin/Android specific +*.class +*.log +*.apk +*.aar +*.dex +*.module + +# Dependency directories +/node_modules +/jspm_packages + +# Gradle +gradle/ +gradlew +gradlew.bat + +# Local configuration file +local.properties + +# Log files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +/captures + +# Intellij +*.ipr +*.iws + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +lint/reports/ \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..3b23d6d --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,43 @@ +plugins { + id 'com.android.application' + id 'kotlin-android' +} + +android { + compileSdkVersion 30 + defaultConfig { + applicationId "com.wifiscanner" + minSdkVersion 29 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.21" + implementation 'androidx.core:core-ktx:1.6.0' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'com.google.android.material:material:1.4.0' + + // Testing dependencies + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.mockito:mockito-core:3.11.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' +} \ No newline at end of file diff --git a/src/main/kotlin/com/wifiscanner/models/WiFiSecurity.kt b/src/main/kotlin/com/wifiscanner/models/WiFiSecurity.kt new file mode 100644 index 0000000..7c39864 --- /dev/null +++ b/src/main/kotlin/com/wifiscanner/models/WiFiSecurity.kt @@ -0,0 +1,14 @@ +package com.wifiscanner.models + +/** + * Represents the security type of a WiFi network. + * + * @property type The human-readable security type + * @property description A detailed description of the security type + * @property level A numeric representation of security strength (higher is more secure) + */ +data class WiFiSecurityType( + val type: String, + val description: String, + val level: Int +) \ No newline at end of file diff --git a/src/main/kotlin/com/wifiscanner/utils/WiFiSecurityMapper.kt b/src/main/kotlin/com/wifiscanner/utils/WiFiSecurityMapper.kt new file mode 100644 index 0000000..d9a08a7 --- /dev/null +++ b/src/main/kotlin/com/wifiscanner/utils/WiFiSecurityMapper.kt @@ -0,0 +1,72 @@ +package com.wifiscanner.utils + +import com.wifiscanner.models.WiFiSecurityType + +/** + * Utility class for mapping WiFi network capabilities to security types. + */ +object WiFiSecurityMapper { + /** + * Maps raw network capabilities to a WiFiSecurityType. + * + * @param capabilities Raw network capabilities string + * @return WiFiSecurityType representing the network's security + */ + fun mapSecurityType(capabilities: String?): WiFiSecurityType { + return when { + capabilities.isNullOrBlank() -> WiFiSecurityType( + "Unknown", + "Unable to determine network security", + 0 + ) + capabilities.contains("WPA3", ignoreCase = true) -> WiFiSecurityType( + "WPA3", + "Most advanced WiFi security protocol", + 5 + ) + capabilities.contains("WPA2", ignoreCase = true) -> WiFiSecurityType( + "WPA2", + "Strong encryption with improved security over WPA", + 4 + ) + capabilities.contains("WPA", ignoreCase = true) -> WiFiSecurityType( + "WPA", + "Older security protocol with moderate protection", + 3 + ) + capabilities.contains("WEP", ignoreCase = true) -> WiFiSecurityType( + "WEP", + "Weak and outdated security protocol", + 1 + ) + capabilities.contains("Open", ignoreCase = true) -> WiFiSecurityType( + "Open", + "No encryption, completely unsecured network", + 0 + ) + else -> WiFiSecurityType( + "Other", + "Unrecognized security type", + 2 + ) + } + } + + /** + * Generates a color based on the security level. + * + * @param securityType WiFiSecurityType to determine color for + * @return Color resource ID representing security level + */ + fun getSecurityColor(securityType: WiFiSecurityType): Int { + return when (securityType.level) { + 0 -> android.R.color.holo_red_dark // Open/No Security + 1 -> android.R.color.holo_red_light // Very Weak + 2 -> android.R.color.holo_orange_dark // Weak + 3 -> android.R.color.holo_orange_light // Moderate + 4 -> android.R.color.holo_green_light // Strong + 5 -> android.R.color.holo_green_dark // Most Secure + else -> android.R.color.darker_gray // Unknown + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/wifiscanner/utils/WiFiSecurityMapperTest.kt b/src/test/kotlin/com/wifiscanner/utils/WiFiSecurityMapperTest.kt new file mode 100644 index 0000000..bff3f64 --- /dev/null +++ b/src/test/kotlin/com/wifiscanner/utils/WiFiSecurityMapperTest.kt @@ -0,0 +1,57 @@ +package com.wifiscanner.utils + +import com.wifiscanner.models.WiFiSecurityType +import org.junit.Assert.* +import org.junit.Test + +class WiFiSecurityMapperTest { + + @Test + fun `mapSecurityType should return WPA3 for WPA3 capabilities`() { + val capabilities = "[WPA3-PSK-CCMP]" + val result = WiFiSecurityMapper.mapSecurityType(capabilities) + + assertEquals("WPA3", result.type) + assertEquals("Most advanced WiFi security protocol", result.description) + assertEquals(5, result.level) + } + + @Test + fun `mapSecurityType should return WPA2 for WPA2 capabilities`() { + val capabilities = "[WPA2-PSK-CCMP]" + val result = WiFiSecurityMapper.mapSecurityType(capabilities) + + assertEquals("WPA2", result.type) + assertEquals("Strong encryption with improved security over WPA", result.description) + assertEquals(4, result.level) + } + + @Test + fun `mapSecurityType should return Open for open network`() { + val capabilities = "" + val result = WiFiSecurityMapper.mapSecurityType(capabilities) + + assertEquals("Open", result.type) + assertEquals("No encryption, completely unsecured network", result.description) + assertEquals(0, result.level) + } + + @Test + fun `mapSecurityType should return Unknown for null capabilities`() { + val capabilities = null + val result = WiFiSecurityMapper.mapSecurityType(capabilities) + + assertEquals("Unknown", result.type) + assertEquals("Unable to determine network security", result.description) + assertEquals(0, result.level) + } + + @Test + fun `getSecurityColor returns correct color for different security levels`() { + val openSecurity = WiFiSecurityType("Open", "Unsecured", 0) + val wpa3Security = WiFiSecurityType("WPA3", "Secure", 5) + + assertEquals(android.R.color.holo_red_dark, WiFiSecurityMapper.getSecurityColor(openSecurity)) + assertEquals(android.R.color.holo_green_dark, WiFiSecurityMapper.getSecurityColor(wpa3Security)) + } +} \ No newline at end of file