3 Commits

Author SHA1 Message Date
c0742cef5d Update README.md 2022-04-09 23:10:27 +02:00
6f4320b074 Update full_description.txt 2022-04-09 23:07:41 +02:00
000f2ee655 Delete zbar.jar 2022-04-09 23:04:52 +02:00
37 changed files with 378 additions and 1412 deletions

2
.idea/compiler.xml generated
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" /> <bytecodeTargetLevel target="11" />
</component> </component>
</project> </project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_2_API_24.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-01-19T17:01:06.009496Z" />
</component>
</project>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

6
.idea/gradle.xml generated
View File

@ -4,16 +4,16 @@
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
</set> </set>
</option> </option>
<option name="resolveExternalAnnotations" value="false" /> <option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings> </GradleProjectSettings>
</option> </option>
</component> </component>

View File

@ -1,8 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ExtractMethodRecommender" enabled="true" level="WARNING" enabled_by_default="true">
<option name="minLength" value="515" />
</inspection_tool>
</profile>
</component>

10
.idea/migrations.xml generated
View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

3
.idea/misc.xml generated
View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
@ -10,7 +11,7 @@
</map> </map>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@ -5,13 +5,4 @@ It can also open links to userpages of Bookwyrm users and it can scan ISBN codes
This application works on: Android 6 and above. This application works on: Android 6 and above.
And if you want to know, I am [`@StoryDragon@books.storydragon.nl`](https://books.storydragon.nl/user/storydragon) on BookWyrm. And if you want to know, I am `@StoryDragon@wyrms.de` on BookWyrm.
For the ISBN-scanning I use the library zxing-android-embedded.
The barcode icon that is added for instances that do not have ISBN-scanning by default comes from the Remix Icon project.
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/nl.privacydragon.bookwyrm/)
Or download the latest APK from the [Releases Section](https://github.com/PrivacyDragon/Bookwyrm_Android/releases/latest).

View File

@ -3,14 +3,14 @@ plugins {
} }
android { android {
compileSdk 34 compileSdk 31
defaultConfig { defaultConfig {
applicationId "nl.privacydragon.bookwyrm" applicationId "nl.privacydragon.bookwyrm"
minSdk 23 minSdk 23
targetSdk 34 targetSdk 31
versionCode 15 versionCode 7
versionName "1.3.8" versionName "1.3.0"
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
} }
@ -18,7 +18,6 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
vcsInfo.include false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
@ -26,24 +25,18 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
namespace 'nl.privacydragon.bookwyrm'
dependenciesInfo {
includeInApk false
includeInBundle false
}
} }
dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation platform('org.jetbrains.kotlin:kotlin-bom:2.1.0')
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.google.zxing:core:3.5.3' implementation 'com.google.zxing:core:3.3.0'
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar' implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
implementation 'org.conscrypt:conscrypt-android:2.5.2' //implementation 'com.github.yuriy-budiyev:code-scanner:2.1.2'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
} }

Binary file not shown.

Binary file not shown.

View File

@ -11,27 +11,10 @@
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 15, "versionCode": 7,
"versionName": "1.3.8", "versionName": "1.3.0",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],
"elementType": "File", "elementType": "File"
"baselineProfiles": [
{
"minApi": 28,
"maxApi": 30,
"baselineProfiles": [
"baselineProfiles/1/app-release.dm"
]
},
{
"minApi": 31,
"maxApi": 2147483647,
"baselineProfiles": [
"baselineProfiles/0/app-release.dm"
]
}
],
"minSdkVersionForDexing": 23
} }

View File

@ -1,756 +1,246 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="nl.privacydragon.bookwyrm">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" />
<meta-data
android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />
<application <application
android:fullBackupContent="false" android:allowBackup="false"
android:dataExtractionRules="@xml/backup_rules"
android:icon="@mipmap/ic_launcher_wyrm" android:icon="@mipmap/ic_launcher_wyrm"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_wyrm_round" android:roundIcon="@mipmap/ic_launcher_wyrm_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Bookwyrm"> android:theme="@style/Theme.Bookwyrm">
<meta-data
android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />
<activity <activity
android:name=".HandlerActivity" android:name=".HandlerActivity"
android:exported="true"> android:exported="true">
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="wyrms.de" /> android:host="wyrms.de"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="bookwyrm.social" /> android:host="bookwyrm.social"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="book.dansmonorage.blue" /> android:host="book.dansmonorage.blue"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="yyyyy.club" /> android:host="yyyyy.club"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="books.mxhdr.net" /> android:host="books.mxhdr.net"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="ziurkes.group.lt" /> android:host="ziurkes.group.lt"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="books.solarpunk.moe" /> android:host="books.solarpunk.moe"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="reading.taks.garden" /> android:host="reading.taks.garden"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="bookwyrm.spaceling.sh" /> android:host="bookwyrm.spaceling.sh"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="lire.boitam.eu" /> android:host="lire.boitam.eu"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="kirja.casa" /> android:host="kirja.casa"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="books.badwolfbay.games" /> android:host="books.badwolfbay.games"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="books.unexist.dev" /> android:host="books.unexist.dev"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="bookwyrm.cincodenada.com" /> android:host="bookwyrm.cincodenada.com"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="books.underscore.world" /> android:host="books.underscore.world"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="bookwyrm.tardis.pw" /> android:host="bookwyrm.tardis.pw"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="masstoc.io" /> android:host="tankie.ml"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="tankie.ml" /> android:host="masstoc.io"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="books.mennisch.net" /> android:host="books.mennisch.net"
android:pathPrefix="/user/"
android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data
<data android:host="bookwyrm.pt" /> android:host="bookwyrm.pt"
</intent-filter> android:pathPrefix="/user/"
<intent-filter android:autoVerify="true"> android:scheme="https" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.lond.com.br" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="good.franv.site" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.solarpunkanarchism.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="shoko.one" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.mennisch.net" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookrastinating.com" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="library.cybre.city" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.storydragon.nl" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="reading.unbl.ink" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="velhaestante.com.br" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.gatti.ninja" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.theunseen.city" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="lore.livellosegreto.it" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.jascha.wtf" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bw.diaspodon.fr" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.tilde.zone" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="libros.mistli.net" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="orreadi.com" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="lectura.social" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookishbook.club" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.tech" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="comelibros.club" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="ramblingreaders.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="secretbearlibrary.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="grimoire.party" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="biblio.thekambattu.rocks" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="buecher.pnpde.social" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bouquins.zbeul.fr" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="boundcovers.com" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="tomes.tchncs.de" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bw.heraut.eu" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.welhaba.mx" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.regenpfeifer.net" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="libroj.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookshelf.hutchie.scot" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="b.skobk.in" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="outside.ofa.dog" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.babb.no" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="millefeuilles.cloud" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="grimoire.social" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.it" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.chriswb.dev" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="leselog.de" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="reads.netsphere.pub" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bookwyrm.world" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="reads.caskey-demaret.se" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="library.southfox.me" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="wyrm.maraval.net" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="sfba.club" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="linguistic.earth" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="wyrmsign.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="book.dadalo.pl" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.bimbiribase.xyz" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="bolha.review" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="plaerdemavida.cat" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="paperjale.eus" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.duck.cafe" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="books.hccp.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="library.chatan.cc" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="knowledgehub.social" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="alexandria.the1977project.org" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity

View File

@ -1,41 +1,63 @@
package nl.privacydragon.bookwyrm; package nl.privacydragon.bookwyrm;
import static androidx.core.content.ContextCompat.startActivity;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
//import android.support.v4.app.ActivityCompat;
//import android.support.v4.content.ContextCompat;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.webkit.ConsoleMessage;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback; import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest; import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.journeyapps.barcodescanner.ScanContract; import com.google.zxing.integration.android.IntentIntegrator;
import com.journeyapps.barcodescanner.ScanOptions; import com.google.zxing.integration.android.IntentResult;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
public class HandlerActivity extends AppCompatActivity { public class HandlerActivity extends AppCompatActivity {
WebView myWebView; WebView myWebView;
ProgressBar LoadIndicator; ProgressBar LoadIndicator;
public ValueCallback<Uri[]> omhooglader;
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -46,76 +68,39 @@ public class HandlerActivity extends AppCompatActivity {
String appLinkAction = appLinkIntent.getAction(); String appLinkAction = appLinkIntent.getAction();
Uri appLinkData = appLinkIntent.getData(); Uri appLinkData = appLinkIntent.getData();
// End of auto-generated stuff // End of auto-generated stuff
ActivityResultLauncher<Intent> voodooLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
if (omhooglader == null)
return;
omhooglader.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
} else {
omhooglader.onReceiveValue(null);
}
});
LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3); LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3);
myWebView = (WebView) findViewById(R.id.webview); myWebView = (WebView) findViewById(R.id.webview);
myWebView.setVisibility(View.GONE);
myWebView.getSettings().setJavaScriptEnabled(true); myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setDomStorageEnabled(true); myWebView.getSettings().setDomStorageEnabled(true);
myWebView.getSettings().setAllowFileAccess(true);
myWebView.getSettings().setAllowContentAccess(true);
myWebView.addJavascriptInterface(new Object() myWebView.addJavascriptInterface(new Object()
{ {
@JavascriptInterface // For API 17+ @JavascriptInterface // For API 17+
public void performClick(String what) public void performClick()
{ {
if (!what.contains("[object Window]")) { //For some reason the function has to be called when the event listener is attached to the button. So, by adding in 'this', it is possible to make sure to only act when the thing that called the function is NOT the window, but the button.
ScanBarCode(); ScanBarCode();
}
} }
}, "scan"); }, "scan");
myWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (omhooglader != null) {
//omhooglader.onReceiveValue(null);
omhooglader = null;
}
omhooglader = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try {
voodooLauncher.launch(intent);
} catch (ActivityNotFoundException grrr){
omhooglader = null;
return false;
}
return true;
}
});
//myWebView.addJavascriptInterface(new HandlerActivity.WebAppInterface(this), "Android"); //myWebView.addJavascriptInterface(new HandlerActivity.WebAppInterface(this), "Android");
//The user credentials are stored in the shared preferences, so first they have to be read from there. //The user credentials are stored in the shared preferences, so first they have to be read from there.
String defaultValue = "none"; String defaultValue = "none";
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE); SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
String server = sharedPref.getString(getString(R.string.server), defaultValue); String server = sharedPref.getString(getString(R.string.server), defaultValue);
//SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE); SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
//String name = sharedPrefName.getString(getString(R.string.name), defaultValue); String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
//SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE); SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
//String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue); String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
//SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE); SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
//String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue); String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
//If there is nothing configured yet, the user should be redirected to the main screen for logging in. //If there is nothing configured yet, the user should be redirected to the main screen for logging in.
if (server == "none") { if (server == "none") {
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class)); startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class));
} }
String pathMaybe = appLinkData.getPath(); String pathMaybe = appLinkData.getPath();
String toGoServer = "bla"; String toGoServer = "bla";
//This bit of code regelt wanneer de webpagina wordt weergegeven. It is quite handig then om dan ook "book" toe te laten, zodat ook boeken in de app bekeken kunnen worden... if (pathMaybe.contains("user")) {
if (pathMaybe.contains("user") || pathMaybe.contains("book")) {
//If the path contains 'user', it is a user profile, unless it is followed by something like 'review'. //If the path contains 'user', it is a user profile, unless it is followed by something like 'review'.
if (pathMaybe.contains("review") || pathMaybe.contains("generatednote") || pathMaybe.contains("quotation") || pathMaybe.contains("comment") || pathMaybe.contains("book")) { if (pathMaybe.contains("review") || pathMaybe.contains("generatednote") || pathMaybe.contains("quotation") || pathMaybe.contains("comment") ) {
toGoServer = "https://" + appLinkData.getHost() + pathMaybe; toGoServer = "https://" + appLinkData.getHost() + pathMaybe;
} }
else { else {
@ -124,110 +109,90 @@ public class HandlerActivity extends AppCompatActivity {
toGoServer = "https://" + server + "/user/" + atUser; toGoServer = "https://" + server + "/user/" + atUser;
} }
} else { } else {
//If the toGoServer string remains "bla", dan zal de user when they teruggaan uitkomen op https://bla/, which is 'not allowed'.
//So, maybe here, just to be sure, assign the value of the user's own server to the toGoServer variabele.
//After that, since apparently I have decided that the URL the user tried to follow is not valid in my application, redirect them to StartActivity.
toGoServer = "https://" + server;
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class)); startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
} }
//Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed. //Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed.
//First get the keystore thing. //First get the keystore thing.
// KeyStore keyStore = null; KeyStore keyStore = null;
// try { try {
// keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore = KeyStore.getInstance("AndroidKeyStore");
// } catch (KeyStoreException e) { } catch (KeyStoreException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// //Then, load it. or something. To make sure that it can be used. //Then, load it. or something. To make sure that it can be used.
// try { try {
// keyStore.load(null); keyStore.load(null);
// } catch (CertificateException e) { } catch (CertificateException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (IOException e) { } catch (IOException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// //Next, retrieve the key to be used for the decryption. //Next, retrieve the key to be used for the decryption.
// Key DragonLikeKey = null; Key DragonLikeKey = null;
// try { try {
// DragonLikeKey = keyStore.getKey("BookWyrm", null); DragonLikeKey = keyStore.getKey("BookWyrm", null);
// } catch (KeyStoreException e) { } catch (KeyStoreException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (UnrecoverableKeyException e) { } catch (UnrecoverableKeyException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// //Do something with getting the/a cipher or something. //Do something with getting the/a cipher or something.
// Cipher c = null; Cipher c = null;
// try { try {
// c = Cipher.getInstance("AES/GCM/NoPadding"); c = Cipher.getInstance("AES/GCM/NoPadding");
// } catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (NoSuchPaddingException e) { } catch (NoSuchPaddingException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// //And then initiating the cipher, so it can be used. //And then initiating the cipher, so it can be used.
// try { try {
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes())); c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
// } catch (InvalidAlgorithmParameterException e) { } catch (InvalidAlgorithmParameterException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// //Decrypt the password! //Decrypt the password!
// byte[] truePass = null; byte[] truePass = null;
// try { try {
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT)); truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
// } catch (BadPaddingException e) { } catch (BadPaddingException e) {
// e.printStackTrace(); e.printStackTrace();
// } catch (IllegalBlockSizeException e) { } catch (IllegalBlockSizeException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// //Convert the decrypted password back to a string. //Convert the decrypted password back to a string.
// String passw = new String(truePass, StandardCharsets.UTF_8); String passw = new String(truePass, StandardCharsets.UTF_8);
//String wacht = passw.replaceAll("'", "\\\\'");
//A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page. //A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page.
String finalToGoServer = toGoServer; String finalToGoServer = toGoServer;
myWebView.setWebViewClient(new HandlerActivity.MyWebViewClient() { myWebView.setWebViewClient(new HandlerActivity.MyWebViewClient() {
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
LoadIndicator.setVisibility(View.GONE); LoadIndicator.setVisibility(View.GONE);
myWebView.setVisibility(View.VISIBLE);
//view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + wacht + "'; ;})()"); view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + passw + "'; ;})()");
//view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()"); view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()");
//view.loadUrl("javascript:(function() { if (window.location.href == '" + finalToGoServer + "' && !/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) { document.getElementsByName(\"login\")[0].submit();} ;})()"); view.loadUrl("javascript:(function() { if (window.location.href == '" + finalToGoServer + "' && !/(review|generatednote|quotation|comment)/i.test(window.location.href)) { document.getElementsByName(\"login\")[0].submit();} ;})()");
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "') { document.getElementsByName(\"login\")[0].submit();} ;})()"); view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "') { document.getElementsByName(\"login\")[0].submit();} ;})()");
view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) {" + view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment)/i.test(window.location.href)) { document.getElementsByClassName(\"block\")[0].innerHTML = ` <a href=\"https://"+ server +"\" class=\"button\" data-back=\"\">\n" +
"blocks = document.getElementsByClassName('block');" +
"for (let element of blocks){" +
"if (element.localName == 'header') { " +
"element.innerHTML = ` <a href=\"https://"+ server +"\" class=\"button\" data-back=\"\">\n" +
" <span class=\"icon icon-arrow-left\" aria-hidden=\"true\"></span>\n" + " <span class=\"icon icon-arrow-left\" aria-hidden=\"true\"></span>\n" +
" <span><b>Back to homeserver</b></span>\n" + " <span><b>Back to homeserver</b></span>\n" +
"</a>`;" + " </a>`;} ;})()");
"break;" +
"}" +
"}" +
"} ;})()");
view.loadUrl("javascript:(function() { " + view.loadUrl("javascript:(function() { " +
"if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" + "const ISBN = document.createElement(\"p\");" +
"let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" + "ISBN.innerHTML = '<br/>Click to scan ISBN';" +
"ISBN_Button.replaceWith(ISBN_Button.cloneNode(true));" + "ISBN.addEventListener('click', () => {" +
"document.querySelectorAll(\"[data-modal-open]\")[0].addEventListener('click', () => {" + " scan.performClick();" +
"scan.performClick(this);" +
"});" + "});" +
"} else {" + "const NewCenter = document.createElement(\"center\");" +
"let ISBN = document.createElement(\"div\");" + "NewCenter.append(ISBN);" +
"ISBN.class = 'control';" + "nav = document.body;" +
//"ISBN.class = 'button';" + "nav.insertBefore(NewCenter, nav.children[0]);" +
//"ISBN.type = 'button';" +
"ISBN.innerHTML = '<button class=\"button\" type=\"button\" onclick=\"scan.performClick(this)\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path fill=\"none\" d=\"M0 0h24v24H0z\"/><path d=\"M4 5v14h16V5H4zM3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm3 4h3v10H6V7zm4 0h2v10h-2V7zm3 0h1v10h-1V7zm2 0h3v10h-3V7z\"/></svg><span class=\"is-sr-only\">Search</span></button>';" +
"nav = document.getElementsByClassName(\"field has-addons\")[0];" +
"nav.appendChild(ISBN);" +
"}" +
";})()"); ";})()");
} }
}); });
@ -235,7 +200,7 @@ public class HandlerActivity extends AppCompatActivity {
// Need to accept permissions to use the camera // Need to accept permissions to use the camera
@Override @Override
public void onPermissionRequest(PermissionRequest request) { public void onPermissionRequest(PermissionRequest request) {
String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE; String permission = Manifest.permission.CAMERA;
int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission); int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission);
if (grant != PackageManager.PERMISSION_GRANTED) { if (grant != PackageManager.PERMISSION_GRANTED) {
String[] permission_list = new String[1]; String[] permission_list = new String[1];
@ -245,7 +210,7 @@ public class HandlerActivity extends AppCompatActivity {
request.grant(request.getResources()); request.grant(request.getResources());
final String[] requestedResources = request.getResources(); final String[] requestedResources = request.getResources();
for (String r : requestedResources) { for (String r : requestedResources) {
if (r.equals(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) { if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE}); request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
break; break;
} }
@ -253,27 +218,10 @@ public class HandlerActivity extends AppCompatActivity {
} }
});*/ });*/
//Here, load the login page of the server. That actually does all that is needed. //Here, load the login page of the server. That actually does all that is needed.
//myWebView.loadUrl("https://serratus.github.io/quaggaJS/examples/live_w_locator.html");
myWebView.loadUrl(toGoServer); myWebView.loadUrl(toGoServer);
} }
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
result -> {
if(result.getContents() == null) {
Toast.makeText(HandlerActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(HandlerActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
myWebView.loadUrl("Javascript:(function() {" +
"try {" +
"document.getElementById('tour-search').value = " + result.getContents() + ";" +
"} catch {" +
"document.getElementById('search_input').value = " + result.getContents() + ";" +
"}" +
"document.getElementsByTagName('form')[0].submit();" +
";})()");
LoadIndicator.setVisibility(View.VISIBLE);
}
});
public void ScanBarCode() { public void ScanBarCode() {
String permission = Manifest.permission.CAMERA; String permission = Manifest.permission.CAMERA;
int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission); int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission);
@ -282,19 +230,54 @@ public class HandlerActivity extends AppCompatActivity {
permission_list[0] = permission; permission_list[0] = permission;
ActivityCompat.requestPermissions(HandlerActivity.this, permission_list, 1); ActivityCompat.requestPermissions(HandlerActivity.this, permission_list, 1);
} }
ScanOptions eisen = new ScanOptions();
eisen.setDesiredBarcodeFormats(ScanOptions.EAN_13); IntentIntegrator intentIntegrator = new IntentIntegrator(HandlerActivity.this);
eisen.setBeepEnabled(true); intentIntegrator.setDesiredBarcodeFormats(intentIntegrator.ALL_CODE_TYPES);
eisen.setCameraId(0); intentIntegrator.setBeepEnabled(true);
eisen.setPrompt("SCAN ISBN"); intentIntegrator.setCameraId(0);
eisen.setBarcodeImageEnabled(false); intentIntegrator.setPrompt("SCAN");
barcodeLanceerder.launch(eisen); intentIntegrator.setBarcodeImageEnabled(false);
intentIntegrator.initiateScan();
//return "blup"; //return "blup";
//return "bla"; //return "bla";
} }
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult Result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (Result != null) {
if (Result.getContents() == null) {
Toast.makeText(this, "cancelled", Toast.LENGTH_SHORT).show();
} else {
Log.d("MainActivity", "Scanned");
myWebView.loadUrl("Javascript:(function() {document.getElementById('search_input').value = " + Result.getContents() + ";" +
"document.getElementsByTagName('form')[0].submit(); ;})()");
LoadIndicator.setVisibility(View.VISIBLE);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
/*public class WebAppInterface {
Context mContext;
//Instantiate the interface and set the context
WebAppInterface(Context c) {
mContext = c;
}
// Show a toast from the web page
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history // Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack(); myWebView.goBack();
@ -302,17 +285,9 @@ public class HandlerActivity extends AppCompatActivity {
} }
// If it wasn't the Back key or there's no web page history, bubble up to the default // If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity) // system behavior (probably exit the activity)
return super.onKeyUp(keyCode, event); return super.onKeyDown(keyCode, event);
} }
@Override //Here is code to make sure that links of the bookwyrm server are handled withing the webview client, instead of having it open in the default browser.
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return super.onKeyLongPress(keyCode, event);
}
//Here is code to make sure that links of the bookwyrm server are handled within the webview client, instead of having it open in the default browser.
//Yes, I used the web for this too. //Yes, I used the web for this too.
private class MyWebViewClient extends WebViewClient { private class MyWebViewClient extends WebViewClient {
@Override @Override

View File

@ -6,6 +6,7 @@ import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties; import android.security.keystore.KeyProperties;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.util.Base64; import android.util.Base64;
import android.view.View; import android.view.View;
@ -43,7 +44,7 @@ public class MainActivity extends AppCompatActivity {
SharedPreferences sharedPref = MainActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE); SharedPreferences sharedPref = MainActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
String defaultValue = "none"; String defaultValue = "none";
String server = sharedPref.getString(getString(R.string.server), defaultValue); String server = sharedPref.getString(getString(R.string.server), defaultValue);
if (!"none".equals(server)) { if (server != "none") {
startActivity(new Intent(MainActivity.this, nl.privacydragon.bookwyrm.StartActivity.class)); startActivity(new Intent(MainActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
} }
} }
@ -53,9 +54,8 @@ public class MainActivity extends AppCompatActivity {
String ALLOWED_CHARACTERS ="0123456789qwertyuiopasdfghjklzxcvbnm!@#$%^&*()_+=][{}"; String ALLOWED_CHARACTERS ="0123456789qwertyuiopasdfghjklzxcvbnm!@#$%^&*()_+=][{}";
final Random random=new Random(); final Random random=new Random();
final StringBuilder sb=new StringBuilder(12); final StringBuilder sb=new StringBuilder(12);
for(int i = 0; i< 12; ++i) { for(int i = 0; i< 12; ++i)
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length()))); sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
}
return sb.toString(); return sb.toString();
} }
@ -70,7 +70,7 @@ public class MainActivity extends AppCompatActivity {
//All fields are required, so if one of them is empty, the user should see a warning. //All fields are required, so if one of them is empty, the user should see a warning.
if (server.isEmpty() || pass.isEmpty() || name.isEmpty()) { if (server.isEmpty() || pass.isEmpty() || name.isEmpty()) {
TextView ErrorMessage = (TextView) findViewById(R.id.textView5); TextView ErrorMessage = (TextView) findViewById(R.id.textView5);
ErrorMessage.setTextColor(Color.YELLOW); ErrorMessage.setTextColor(Color.RED);
ErrorMessage.setText("ERROR: All fields are required!"); ErrorMessage.setText("ERROR: All fields are required!");
} else { } else {
//Likely this will be the first time the program is run. So create a new key thing in the android key store happening. //Likely this will be the first time the program is run. So create a new key thing in the android key store happening.

View File

@ -2,42 +2,32 @@ package nl.privacydragon.bookwyrm;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
//import android.support.v7.app.AppCompatActivity;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.util.Base64; import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest; import android.webkit.WebResourceRequest;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.journeyapps.barcodescanner.ScanContract; import com.google.zxing.integration.android.IntentIntegrator;
import com.journeyapps.barcodescanner.ScanOptions; import com.google.zxing.integration.android.IntentResult;
import org.conscrypt.Conscrypt;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
@ -45,7 +35,6 @@ import java.security.Key;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
@ -55,80 +44,26 @@ import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.GCMParameterSpec;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class StartActivity extends AppCompatActivity { public class StartActivity extends AppCompatActivity {
WebView myWebView; WebView myWebView;
ProgressBar LoadIndicator; ProgressBar LoadIndicator;
public ValueCallback<Uri[]> omhooglader;
String putje = "";
String sessie = "";
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start); setContentView(R.layout.activity_start);
LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3); LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3);
ActivityResultLauncher<Intent> voodooLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
if (omhooglader == null)
return;
omhooglader.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
}
else {
omhooglader.onReceiveValue(null);
}
});
myWebView = (WebView) findViewById(R.id.webview); myWebView = (WebView) findViewById(R.id.webview);
myWebView.setVisibility(View.GONE);
myWebView.getSettings().setUserAgentString(getString(R.string.gebruikersagent));
myWebView.getSettings().setJavaScriptEnabled(true); myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new Object() myWebView.addJavascriptInterface(new Object()
{ {
@JavascriptInterface // For API 17+ @JavascriptInterface // For API 17+
public void performClick(String what) public void performClick()
{ {
if (!what.contains("[object Window]")) { //For some reason the function has to be called when the event listener is attached to the button. So, by adding in 'this', it is possible to make sure to only act when the thing that called the function is NOT the window, but the button.
ScanBarCode(); ScanBarCode();
}
} }
}, "scan"); }, "scan");
myWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (omhooglader != null) {
//omhooglader.onReceiveValue(null);
omhooglader = null;
}
omhooglader = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try {
// String toestemming = Manifest.permission.READ_EXTERNAL_STORAGE;
// int grant = ContextCompat.checkSelfPermission(StartActivity.this, toestemming);
// if (grant != PackageManager.PERMISSION_GRANTED) {
// String[] permission_list = new String[1];
// permission_list[0] = toestemming;
// ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1);
// }
voodooLauncher.launch(intent);
} catch (ActivityNotFoundException grrr){
omhooglader = null;
return false;
}
return true;
}
});
//The user credentials are stored in the shared preferences, so first they have to be read from there. //The user credentials are stored in the shared preferences, so first they have to be read from there.
String defaultValue = "none"; String defaultValue = "none";
SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE); SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
@ -150,340 +85,78 @@ public class StartActivity extends AppCompatActivity {
//Then, load it. or something. To make sure that it can be used. //Then, load it. or something. To make sure that it can be used.
try { try {
keyStore.load(null); keyStore.load(null);
} catch (CertificateException | IOException | NoSuchAlgorithmException e) { } catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
//Next, retrieve the key to be used for the decryption. //Next, retrieve the key to be used for the decryption.
Key DragonLikeKey = null; Key DragonLikeKey = null;
try { try {
DragonLikeKey = keyStore.getKey("BookWyrm", null); DragonLikeKey = keyStore.getKey("BookWyrm", null);
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) { } catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace(); e.printStackTrace();
} }
//Do something with getting the/a cipher or something. //Do something with getting the/a cipher or something.
Cipher c = null; Cipher c = null;
try { try {
c = Cipher.getInstance("AES/GCM/NoPadding"); c = Cipher.getInstance("AES/GCM/NoPadding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace(); e.printStackTrace();
} }
//And then initiating the cipher, so it can be used. //And then initiating the cipher, so it can be used.
try { try {
assert c != null;
c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes())); c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
} catch (InvalidAlgorithmParameterException | InvalidKeyException e) { } catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace(); e.printStackTrace();
} }
//Decrypt the password! //Decrypt the password!
byte[] truePass = null; byte[] truePass = null;
try { try {
truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT)); truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
} catch (BadPaddingException | IllegalBlockSizeException e) { } catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace(); e.printStackTrace();
} }
//Convert the decrypted password back to a string. //Convert the decrypted password back to a string.
String passw = new String(truePass, StandardCharsets.UTF_8); String passw = new String(truePass, StandardCharsets.UTF_8);
//String wacht = passw.replaceAll("'", "\\\\'");
//A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page. //A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page.
myWebView.setWebViewClient(new MyWebViewClient(){ myWebView.setWebViewClient(new MyWebViewClient(){
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
LoadIndicator.setVisibility(View.GONE); LoadIndicator.setVisibility(View.GONE);
myWebView.setVisibility(View.VISIBLE);
//view.loadUrl("javascript:(function() { document.getElementById('id_password_confirm').value = '" + wacht + "'; ;})()"); view.loadUrl("javascript:(function() { document.getElementById('id_password_confirm').value = '" + passw + "'; ;})()");
//view.loadUrl("javascript:(function() { document.getElementById('id_localname_confirm').value = '" + name + "'; ;})()"); view.loadUrl("javascript:(function() { document.getElementById('id_localname_confirm').value = '" + name + "'; ;})()");
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login') { document.getElementsByName(\"login-confirm\")[0].submit();} ;})()"); view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login') { document.getElementsByName(\"login-confirm\")[0].submit();} ;})()");
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login' && document.title != '403 Forbidden') { this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);} ;})()");
view.loadUrl("javascript:(function() { " + view.loadUrl("javascript:(function() { " +
"if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" + "const ISBN = document.createElement(\"p\");" +
"let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" + "ISBN.innerHTML = '<br/>Click to scan ISBN';" +
"ISBN_Button.replaceWith(ISBN_Button.cloneNode(true));" + "ISBN.addEventListener('click', () => {" +
"document.querySelectorAll(\"[data-modal-open]\")[0].addEventListener('click', () => {" + " scan.performClick();" +
"scan.performClick(this);" +
"});" + "});" +
"} else {" + "const NewCenter = document.createElement(\"center\");" +
"let ISBN = document.createElement(\"div\");" + "NewCenter.append(ISBN);" +
"ISBN.class = 'control';" + "nav = document.body;" +
//"ISBN.class = 'button';" + "nav.insertBefore(NewCenter, nav.children[0]);" +
//"ISBN.type = 'button';" + ";})()");
"ISBN.innerHTML = '<button class=\"button\" type=\"button\" onclick=\"scan.performClick(this)\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path fill=\"none\" d=\"M0 0h24v24H0z\"/><path d=\"M4 5v14h16V5H4zM3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm3 4h3v10H6V7zm4 0h2v10h-2V7zm3 0h1v10h-1V7zm2 0h3v10h-3V7z\"/></svg><span class=\"is-sr-only\">Search</span></button>';" +
"nav = document.getElementsByClassName(\"field has-addons\")[0];" +
"nav.appendChild(ISBN);" +
"}" +
";})()"); //This lines replace the ISBN-scan button event listener with one that points to the on-device scanning implementation, if it is available on the instance. If not, the button is added.
} }
}); });
//Here, load the login page of the server. That actually does all that is needed. //Here, load the login page of the server. That actually does all that is needed.
// try { myWebView.loadUrl("https://" + server + "/login");
// getMiddleWareToken(server, name, passw);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// String geheimeToken = null;
// try {
// geheimeToken = getMiddleWareToken(server);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// String gegevens = null;
// try {
// gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(geheimeToken, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
// } catch (UnsupportedEncodingException e) {
// throw new RuntimeException(e);
// }
// myWebView.postUrl("https://" + server + "/login", gegevens.getBytes());
//myWebView.loadUrl("https://" + server + "/login");
// myWebView.setVisibility(View.GONE);
// LoadIndicator.setVisibility(View.VISIBLE);
// android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
//myWebView.loadUrl("javascript:this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);");
//try {
//See if we are already logged in.
CookieManager oven = CookieManager.getInstance();
String koek = oven.getCookie("https://" + server);
if (koek != null) {
if (koek.indexOf("sessionid") != -1) {
myWebView.loadUrl("https://" + server);
} else {
//This should get the login page, retreive the csrf-middlewaretoken, and then log the user in using a POST-request.
try {
getMiddleWareTokenAndLogIn(server, name, passw);
} catch (IOException e) {
throw new RuntimeException(e);
} }
}
} else {
//This should get the login page, retreive the csrf-middlewaretoken, and then log the user in using a POST-request.
try {
getMiddleWareTokenAndLogIn(server, name, passw);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//} catch (IOException e) {
// throw new RuntimeException(e);
//}
}
public void getMiddleWareTokenAndLogIn(String server, String name, String passw) throws IOException {
//Het idee is dat deze functie de loginpagina van de server laadt en dan de 'csrfmiddlewaretoken' uit het inlogformulier haalt,
//Zodat dat dan gebruikt kan worden bij het inloggen.
//Becuase network operations cannot be done on the main/ui thread, create a new thread for this complete function. Yay!
Thread draadje = new Thread(new Runnable() {
@Override
public void run() {
try {
//Load the login page, and do not forget to take some cookies.
Security.insertProviderAt(Conscrypt.newProvider(), 1);
//URL url = new URL("https://" + server + "/");
String speculaas = "";
String speculaasBeslag = "";
//The login page loading is done using OkHttpClient.
OkHttpClient client = new OkHttpClient();
Request aanvraag = new Request.Builder()
.url("https://" + server + "/")
.header("User-Agent", getString(R.string.gebruikersagent))
.build();
//Get an answer!
try (Response antwoord = client.newCall(aanvraag).execute()) {
if (!antwoord.isSuccessful()) throw new IOException("Unexpected code " + antwoord);
//Search the headers for the 'set-cookie' header so we can eat a cookie!
Headers cenna = antwoord.headers();
for (int i = 0; i < cenna.size(); i++) {
if (cenna.name(i).equals("set-cookie")) {
speculaas = cenna.value(i);
speculaasBeslag = speculaas.split(";")[0];
}
}
//And then get the HTML body.
assert antwoord.body() != null;
String zooi = antwoord.body().string();
// CookieManager koekManager = new CookieManager();
// CookieHandler.setDefault(koekManager);
// CookieStore bakker = koekManager.getCookieStore();
// HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// try {
// InputStream ina = new BufferedInputStream(urlConnection.getInputStream());
// byte[] pagina = null;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// pagina = ina.readAllBytes();
// } else {
// //I truly hope that this byte array will always be big enough...
// //The Tiramisu+ way is much better...
// pagina = new byte[30000];
// ina.read(pagina);
// }
// try {
// ina.close();
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// //We should not forget closing the connection we used for hearing what csrf cookie and token we needed.
// urlConnection.disconnect();
// //And now create a string out of the byte array, so we can retreive the middleware token.
// String zooi = new String(pagina);
//Very easy to get the token by taking the text that it is preceded by in the raw html as the regex for a split() function!
String[] opgebroken = zooi.split("name=\"csrfmiddlewaretoken\" value=\"");
//For that gives as second element the token, followed by all the following html code. Then strip that code off, using the immediately following characters as regex.
String[] breukjes = opgebroken[1].split("\">");
//Of course, the token is then the first element in our array.
String token = breukjes[0];
//Log.d("botbreuk", token);
String gegevens = null;
//Initiate some strings to use for the delicious csrf cookie.
//String speculaas = "", THT = "";
// //How to get the cookies? First get the cookie collection, the cookie box so to say, and then...
// List<HttpCookie> koektrommel = bakker.get(URI.create("https://" + server));
// Log.d("koek", koektrommel.toString());
// //... for every cookie in it check to see if it is the csrftoken named cookie.
// for (int i = 0; i < koektrommel.size(); ++i) {
// HttpCookie koekje = koektrommel.get(i);
// if (Objects.equals(koekje.getName(), "csrftoken")) {
// //If it is the csrftoken cookie, get the value of it, and the expiration date of it.
// speculaas = koekje.toString();
// THT = String.valueOf(koekje.getMaxAge());
// //Log.d("domein", koekje.getDomain());
// }
// }
//And then set the data string up for use in the POST request, with the csrf middleware token, the username, and the password.
try {
gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(token, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
RequestBody keurslijf = new FormBody.Builder()
.add("csrfmiddlewaretoken", token)
.add("localname", name)
.add("password", passw)
.build();
String finalGegevens = gegevens;
//Log.d("gegevens", finalGegevens);
//Log.d("beslag", speculaasBeslag);
String finalSpeculaas = speculaas;
//String finalTHT = THT;
logInAndGetHTML(server, keurslijf, speculaasBeslag);
//Then we have to run a bit of code on the main (UI) thread. To be able to work with the webview...
runOnUiThread(new Runnable() {
@Override
public void run() {
//First we have to get the cookie manager of the webview, so we can hand it the csrf cookie.
//Without being fed the correct csrf cookie, the Wyrm will refuse our request. The wyrm is a very picky eater!
CookieManager oven = CookieManager.getInstance();
//Bake the cookie into the webview.
oven.setCookie("https://" + server, finalSpeculaas);
//And bake the session cookie as well.
oven.setCookie("https://" + server, sessie);
//And then finally it is time to send a POST request from the webview to log in.
//myWebView.postUrl("https://" + server + "/login?next=/", finalGegevens.getBytes());
myWebView.loadDataWithBaseURL("https://" + server, putje, null, null, "https://" + server + "/login");
}
});
} finally {
// //We should not forget closing the connection we used for hearing what csrf cookie and token we needed.
// urlConnection.disconnect();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
//^Here ends all that new Thread() code.
//⇓Run all the code in the thread.
draadje.start();
}
public void logInAndGetHTML(String server, RequestBody lichaam, String speculoos) throws IOException {
// Thread kabel = new Thread(new Runnable() {
// @Override
// public void run() {
// try {
// //Load the login page, and do not forget to take some cookies.
Security.insertProviderAt(Conscrypt.newProvider(), 1);
//Create a client using CookieMonster, so we can retrieve cookies from the redirect.
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new CookieMonster())
.build();
//URL url = new URL("https://" + server + "/");
//CookieManager koekManager = new CookieManager();
//CookieHandler.setDefault(koekManager);
//CookieStore bakker = koekManager.getCookieStore();
Request verzoek = new Request.Builder()
.url("https://" + server + "/login?next=/")
.header("User-Agent", getString(R.string.gebruikersagent))
.addHeader("origin", "https://" + server)
.addHeader("cookie", speculoos)
.post(lichaam)
.build();
try (Response reactie = client.newCall(verzoek).execute()) {
if (!reactie.isSuccessful())
throw new IOException("Unexpected code " + reactie);
assert reactie.body() != null;
putje = reactie.body().string();
}
// HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// urlConnection.setRequestProperty("origin", "https://" + server);
// byte[] paarden = gegevens.getBytes();
// try {
// urlConnection.setDoOutput(true);
// urlConnection.setChunkedStreamingMode(0);
//
// OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
// out.write(paarden);
// out.flush();
//
// InputStream in = new BufferedInputStream(urlConnection.getInputStream());
// byte[] pagina = null;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// pagina = in.readAllBytes();
// } else {
// //I truly hope that this byte array will always be big enough...
// //The Tiramisu+ way is much better...
// pagina = new byte[30000];
// in.read(pagina);
// }
// try {
// in.close();
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// html[0] = new String(pagina);
// } finally {
// urlConnection.disconnect();
// }
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }
// });
// kabel.start();
//Log.d("lichaam", putje);
//return putje;
}
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
result -> {
if(result.getContents() == null) {
Toast.makeText(StartActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(StartActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
myWebView.loadUrl("Javascript:(function() {" +
"try {" +
"document.getElementById('tour-search').value = " + result.getContents() + ";" +
"} catch {" +
"document.getElementById('search_input').value = " + result.getContents() + ";" +
"}" +
"document.getElementsByTagName('form')[0].submit();" +
";})()");
LoadIndicator.setVisibility(View.VISIBLE);
}
});
public void ScanBarCode() { public void ScanBarCode() {
String permission = Manifest.permission.CAMERA; String permission = Manifest.permission.CAMERA;
int grant = ContextCompat.checkSelfPermission(StartActivity.this, permission); int grant = ContextCompat.checkSelfPermission(StartActivity.this, permission);
@ -492,19 +165,39 @@ public class StartActivity extends AppCompatActivity {
permission_list[0] = permission; permission_list[0] = permission;
ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1); ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1);
} }
ScanOptions eisen = new ScanOptions();
eisen.setDesiredBarcodeFormats(ScanOptions.EAN_13); IntentIntegrator intentIntegrator = new IntentIntegrator(StartActivity.this);
eisen.setBeepEnabled(true); intentIntegrator.setDesiredBarcodeFormats(intentIntegrator.ALL_CODE_TYPES);
eisen.setCameraId(0); intentIntegrator.setBeepEnabled(false);
eisen.setPrompt("SCAN ISBN"); intentIntegrator.setCameraId(0);
eisen.setBarcodeImageEnabled(false); intentIntegrator.setPrompt("SCAN ISBN");
barcodeLanceerder.launch(eisen); intentIntegrator.setBarcodeImageEnabled(false);
intentIntegrator.initiateScan();
//return "blup"; //return "blup";
//return "bla"; //return "bla";
} }
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult Result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (Result != null) {
if (Result.getContents() == null) {
Toast.makeText(this, "cancelled", Toast.LENGTH_SHORT).show();
} else {
Log.d("MainActivity", "Scanned");
myWebView.loadUrl("Javascript:(function() {document.getElementById('search_input').value = " + Result.getContents() + ";" +
"document.getElementsByTagName('form')[0].submit(); ;})()");
LoadIndicator.setVisibility(View.VISIBLE);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history // Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack(); myWebView.goBack();
@ -512,44 +205,9 @@ public class StartActivity extends AppCompatActivity {
} }
// If it wasn't the Back key or there's no web page history, bubble up to the default // If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity) // system behavior (probably exit the activity)
return super.onKeyUp(keyCode, event); return super.onKeyDown(keyCode, event);
} }
@Override //Here is code to make sure that links of the bookwyrm server are handled withing the webview client, instead of having it open in the default browser.
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return super.onKeyLongPress(keyCode, event);
}
final class CookieMonster implements Interceptor {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
//Om ingelogd te blijven moeten we het sessiekoekje aan kunnen bieden.
//Die moeten we dan wel eerst uit het koekblik pakken!
Request eersteVerzoek = chain.request();
//Eerst moeten we controleren of er al een sessiekoekje is. Als dat niet zo is, dan is dit het echte eerste verzoek.
if (sessie.isEmpty()) {
//In dat geval halen we de reactie op om het koekje te kunnen pakken!
Response eersteReactie = chain.proceed(chain.request());
Headers hoofden = eersteReactie.headers();
for (int i = 0; i < hoofden.size(); i++) {
if (hoofden.name(i).equals("set-cookie") && hoofden.value(i).startsWith("session")) {
sessie = hoofden.value(i);
}
}
//Nadat we het koekje hebben moet de reactie doorgebriefd worden aan de 'client',
//die dan het volgende verzoek zal gaan doen vanwege de 302-redirect bij het inloggen.
return eersteReactie;
}
//Het koekje is er! Hoera!
//Het nieuwe verzoek moet wel met het sessiekoekje verzonden worden, anders zijn we alsnog niet ingelogd!
Request nieuwVerzoek = eersteVerzoek.newBuilder()
.addHeader("cookie", sessie)
.build();
return chain.proceed(nieuwVerzoek);
}
}
//Here is code to make sure that links of the bookwyrm server are handled within the webview client, instead of having it open in the default browser.
//Yes, I used the web for this too. //Yes, I used the web for this too.
private class MyWebViewClient extends WebViewClient { private class MyWebViewClient extends WebViewClient {
@Override @Override
@ -570,8 +228,6 @@ public class StartActivity extends AppCompatActivity {
@Override @Override
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String url, Bitmap favicon) {
LoadIndicator.setVisibility(View.VISIBLE); LoadIndicator.setVisibility(View.VISIBLE);
//CookieManager oven = CookieManager.getInstance();
//Log.d("oven", oven.getCookie(url));
} }
} }
} }

View File

@ -26,10 +26,10 @@
android:id="@+id/Instance" android:id="@+id/Instance"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="5dp"
android:layout_marginEnd="1dp" android:layout_marginEnd="1dp"
android:layout_marginBottom="262dp" android:layout_marginBottom="262dp"
android:hint="e.g. bookwyrm.social" android:hint="bookwyrm.social"
android:inputType="text" android:inputType="text"
android:minHeight="48dp" android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -41,7 +41,7 @@
android:id="@+id/Username" android:id="@+id/Username"
android:layout_width="409dp" android:layout_width="409dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="1dp"
android:layout_marginEnd="1dp" android:layout_marginEnd="1dp"
android:layout_marginBottom="284dp" android:layout_marginBottom="284dp"
android:hint="Username" android:hint="Username"
@ -55,7 +55,7 @@
<EditText <EditText
android:id="@+id/Password" android:id="@+id/Password"
android:layout_width="match_parent" android:layout_width="409dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginEnd="1dp" android:layout_marginEnd="1dp"
@ -89,10 +89,10 @@
android:id="@+id/textView2" android:id="@+id/textView2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="16dp"
android:layout_marginTop="76dp" android:layout_marginTop="76dp"
android:layout_marginEnd="185dp" android:layout_marginEnd="185dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="35dp"
android:text="Instance. WITHOUT the https part" android:text="Instance. WITHOUT the https part"
app:layout_constraintBottom_toTopOf="@+id/Instance" app:layout_constraintBottom_toTopOf="@+id/Instance"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -107,7 +107,7 @@
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginEnd="41dp" android:layout_marginEnd="41dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="35dp"
android:text="Username" android:text="Username"
app:layout_constraintBottom_toTopOf="@+id/Username" app:layout_constraintBottom_toTopOf="@+id/Username"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -115,21 +115,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/Instance" /> app:layout_constraintTop_toBottomOf="@+id/Instance" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="340dp"
android:layout_marginBottom="10dp"
android:text="Password"
app:layout_constraintBottom_toTopOf="@+id/Password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/Username" />
<Button <Button
android:id="@+id/button" android:id="@+id/button"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -14,7 +14,6 @@
<ProgressBar <ProgressBar
android:id="@+id/progressBar3" android:id="@+id/progressBar3"
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="715dp" android:layout_marginBottom="715dp"

View File

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.Bookwyrm" parent="Theme.AppCompat"> <style name="Theme.Bookwyrm" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">#3298DC</item> <item name="colorPrimary">#3298DC</item>
<item name="colorPrimaryDark">#1B557C</item> <item name="colorPrimaryDark">#1B557C</item>

View File

@ -4,5 +4,4 @@
<string name="name">blup</string> <string name="name">blup</string>
<string name="pw">gloep</string> <string name="pw">gloep</string>
<string name="q">wheeeee</string> <string name="q">wheeeee</string>
<string name="gebruikersagent">Bookwyrm Android/1.3.8</string>
</resources> </resources>

View File

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.Bookwyrm" parent="Theme.AppCompat"> <style name="Theme.Bookwyrm" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">#3298DC</item> <item name="colorPrimary">#3298DC</item>
<item name="colorPrimaryDark">#1B557C</item> <item name="colorPrimaryDark">#1B557C</item>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<exclude domain="root" path="."/>
</cloud-backup>
<device-transfer>
<exclude domain="root" path="."/>
</device-transfer>
</data-extraction-rules>

View File

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id 'com.android.application' version '8.8.0' apply false id 'com.android.application' version '7.1.1' apply false
id 'com.android.library' version '8.8.0' apply false id 'com.android.library' version '7.1.1' apply false
} }
task clean(type: Delete) { task clean(type: Delete) {

View File

@ -1,3 +0,0 @@
* Fixed a bug with the barcode scanning. Now you can scan barcodes again.
* Dependencies have been updated to newest versions.
* More Bookwyrm instances have been added.

View File

@ -1,5 +0,0 @@
The same as release 1.3.3, but not the one bug is actually fixed for real...
* Fixed a bug with the barcode scanning. Now you can scan barcodes again.
* Dependencies have been updated to newest versions.
* More Bookwyrm instances have been added.

View File

@ -1,6 +0,0 @@
* It is finally possible to add book covers from your own device storage.
* You can now return to the initial log-in screen by long-pressing the 'back' button.
* Dependencies have been updated to newest versions.
* Compiled for up to Android 14 now.
* Deprecated pieces of code have been rewritten.
* More Bookwyrm instances have been added.

View File

@ -1,5 +0,0 @@
* Fixed some log-in problems.
* Changed colour of warning text to be better visible.
* Disabled inclusion of dependencies info and VCS info, fixing build problems for F-Droid.
* Long-press now actually works.
* Other minor changes

View File

@ -1 +0,0 @@
* Significant log-in improvements, including better security.

View File

@ -1,5 +0,0 @@
Fixing what turned out not to work for unreleased version 1.3.7:
* Significant log-in improvements, including better security.
Further changes:
* The app now uses a custom User-Agent string.
* Two new dependencies have been added: okhttp3, and conscrypt.

View File

@ -1,6 +0,0 @@
* Improved the loading bar.
* The ISBN-scanning feature now works by simply clicking the ISBN button that is used by the instances that have scanning already available.
* For instances that do not support the scanning server-side, there is now instead of the text a button for ISBN-scanning, similar to the standard one.
* More bookwyrm instances added to the ones that can be opened in the app.
* Small bug-fix, so now only ISBN-codes (And other EAN-13 codes) will be scanned.
* Another bug-fix. The modified back button works again.

View File

@ -1,2 +0,0 @@
* Changed the initial screen to dark mode.
* The login screen things are now better aligned.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -18,5 +18,3 @@ android.nonTransitiveRClass=true
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false

View File

@ -1,6 +1,6 @@
#Mon Feb 14 18:09:26 CET 2022 #Mon Feb 14 18:09:26 CET 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME