4 Commits

Author SHA1 Message Date
f2eb043e7f Bug fix for login improvements 2025-01-13 16:43:12 +01:00
e17daa9e41 login improvements 2025-01-13 15:39:56 +01:00
dadaaf2a04 Work in progress 2025-01-12 23:48:20 +01:00
b2eba70188 Update to 1.3.6, fixing bugs and more 2025-01-05 15:30:30 +01:00
16 changed files with 339 additions and 99 deletions

10
.idea/deploymentTargetSelector.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?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>

View File

@ -0,0 +1,8 @@
<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 Normal file
View File

@ -0,0 +1,10 @@
<?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>

17
.idea/runConfigurations.xml generated Normal file
View File

@ -0,0 +1,17 @@
<?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

@ -9,8 +9,8 @@ android {
applicationId "nl.privacydragon.bookwyrm"
minSdk 23
targetSdk 34
versionCode 12
versionName "1.3.5"
versionCode 13
versionName "1.3.6"
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
@ -18,6 +18,7 @@ android {
buildTypes {
release {
minifyEnabled false
vcsInfo.include false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
@ -26,6 +27,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
namespace 'nl.privacydragon.bookwyrm'
dependenciesInfo {
includeInApk false
includeInBundle false
}
}
dependencies {

Binary file not shown.

Binary file not shown.

View File

@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 12,
"versionName": "1.3.5",
"versionCode": 13,
"versionName": "1.3.6",
"outputFile": "app-release.apk"
}
],

View File

@ -9,7 +9,8 @@
<uses-feature android:name="android.hardware.camera" />
<application
android:allowBackup="false"
android:fullBackupContent="false"
android:dataExtractionRules="@xml/backup_rules"
android:icon="@mipmap/ic_launcher_wyrm"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_wyrm_round"

View File

@ -11,7 +11,6 @@ import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Base64;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.JavascriptInterface;
@ -32,23 +31,6 @@ import androidx.core.content.ContextCompat;
import com.journeyapps.barcodescanner.ScanContract;
import com.journeyapps.barcodescanner.ScanOptions;
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 {
WebView myWebView;
@ -118,12 +100,12 @@ public class HandlerActivity extends AppCompatActivity {
String defaultValue = "none";
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
String server = sharedPref.getString(getString(R.string.server), defaultValue);
SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
//SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
//String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
//SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
//String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
//SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
//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 (server == "none") {
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class));
@ -150,61 +132,62 @@ public class HandlerActivity extends AppCompatActivity {
}
//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.
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (KeyStoreException e) {
e.printStackTrace();
}
//Then, load it. or something. To make sure that it can be used.
try {
keyStore.load(null);
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//Next, retrieve the key to be used for the decryption.
Key DragonLikeKey = null;
try {
DragonLikeKey = keyStore.getKey("BookWyrm", null);
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
}
//Do something with getting the/a cipher or something.
Cipher c = null;
try {
c = Cipher.getInstance("AES/GCM/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
//And then initiating the cipher, so it can be used.
try {
c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
//Decrypt the password!
byte[] truePass = null;
try {
truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
//Convert the decrypted password back to a string.
String passw = new String(truePass, StandardCharsets.UTF_8);
// KeyStore keyStore = null;
// try {
// keyStore = KeyStore.getInstance("AndroidKeyStore");
// } catch (KeyStoreException e) {
// e.printStackTrace();
// }
// //Then, load it. or something. To make sure that it can be used.
// try {
// keyStore.load(null);
// } catch (CertificateException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// }
// //Next, retrieve the key to be used for the decryption.
// Key DragonLikeKey = null;
// try {
// DragonLikeKey = keyStore.getKey("BookWyrm", null);
// } catch (KeyStoreException e) {
// e.printStackTrace();
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// } catch (UnrecoverableKeyException e) {
// e.printStackTrace();
// }
// //Do something with getting the/a cipher or something.
// Cipher c = null;
// try {
// c = Cipher.getInstance("AES/GCM/NoPadding");
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// } catch (NoSuchPaddingException e) {
// e.printStackTrace();
// }
// //And then initiating the cipher, so it can be used.
// try {
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
// } catch (InvalidAlgorithmParameterException e) {
// e.printStackTrace();
// } catch (InvalidKeyException e) {
// e.printStackTrace();
// }
// //Decrypt the password!
// byte[] truePass = null;
// try {
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
// } catch (BadPaddingException e) {
// e.printStackTrace();
// } catch (IllegalBlockSizeException e) {
// e.printStackTrace();
// }
// //Convert the decrypted password back to a string.
// 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.
String finalToGoServer = toGoServer;
@ -213,10 +196,10 @@ public class HandlerActivity extends AppCompatActivity {
LoadIndicator.setVisibility(View.GONE);
myWebView.setVisibility(View.VISIBLE);
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_password').value = '" + wacht + "'; ;})()");
//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 == '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)) {" +
"blocks = document.getElementsByClassName('block');" +
"for (let element of blocks){" +
@ -311,7 +294,7 @@ public class HandlerActivity extends AppCompatActivity {
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
public boolean onKeyUp(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
@ -319,7 +302,7 @@ public class HandlerActivity extends AppCompatActivity {
}
// 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)
return super.onKeyDown(keyCode, event);
return super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {

View File

@ -6,7 +6,6 @@ import android.content.SharedPreferences;
import android.graphics.Color;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.view.View;
@ -71,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.
if (server.isEmpty() || pass.isEmpty() || name.isEmpty()) {
TextView ErrorMessage = (TextView) findViewById(R.id.textView5);
ErrorMessage.setTextColor(Color.RED);
ErrorMessage.setTextColor(Color.YELLOW);
ErrorMessage.setText("ERROR: All fields are required!");
} else {
//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

@ -10,6 +10,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Base64;
import android.view.KeyEvent;
@ -32,7 +33,18 @@ import androidx.core.content.ContextCompat;
import com.journeyapps.barcodescanner.ScanContract;
import com.journeyapps.barcodescanner.ScanOptions;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@ -42,6 +54,8 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Objects;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@ -166,6 +180,7 @@ public class StartActivity extends AppCompatActivity {
}
//Convert the decrypted password back to a string.
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.
myWebView.setWebViewClient(new MyWebViewClient(){
@ -173,9 +188,10 @@ public class StartActivity extends AppCompatActivity {
LoadIndicator.setVisibility(View.GONE);
myWebView.setVisibility(View.VISIBLE);
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() { if (window.location.href == 'https://" + server + "/login') { document.getElementsByName(\"login-confirm\")[0].submit();} ;})()");
//view.loadUrl("javascript:(function() { document.getElementById('id_password_confirm').value = '" + wacht + "'; ;})()");
//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.title != '403 Forbidden') { this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);} ;})()");
view.loadUrl("javascript:(function() { " +
"if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" +
"let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" +
@ -197,7 +213,184 @@ public class StartActivity extends AppCompatActivity {
}
});
//Here, load the login page of the server. That actually does all that is needed.
myWebView.loadUrl("https://" + server + "/login");
// try {
// 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 {
getMiddleWareTokenAndLogIn(server, name, passw);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// public void logIn(String lichaam) {
// //First, verkrijg the user credentials.
// //The user credentials are stored in the shared preferences, so first they have to be read from there.
// String defaultValue = "none";
// SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
// String server = sharedPref.getString(getString(R.string.server), defaultValue);
// SharedPreferences sharedPrefName = StartActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
// String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
// SharedPreferences sharedPrefPass = StartActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
// String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
// SharedPreferences sharedPrefMagic = StartActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
// String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
// //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.
// KeyStore keyStore = null;
// try {
// keyStore = KeyStore.getInstance("AndroidKeyStore");
// } catch (KeyStoreException e) {
// e.printStackTrace();
// }
// //Then, load it. or something. To make sure that it can be used.
// try {
// keyStore.load(null);
// } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
// e.printStackTrace();
// }
// //Next, retrieve the key to be used for the decryption.
// Key DragonLikeKey = null;
// try {
// DragonLikeKey = keyStore.getKey("BookWyrm", null);
// } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
// e.printStackTrace();
// }
// //Do something with getting the/a cipher or something.
// Cipher c = null;
// try {
// c = Cipher.getInstance("AES/GCM/NoPadding");
// } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
// e.printStackTrace();
// }
// //And then initiating the cipher, so it can be used.
// try {
// assert c != null;
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
// } catch (InvalidAlgorithmParameterException | InvalidKeyException e) {
// e.printStackTrace();
// }
// //Decrypt the password!
// byte[] truePass = null;
// try {
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
// } catch (BadPaddingException | IllegalBlockSizeException e) {
// e.printStackTrace();
// }
// //Convert the decrypted password back to a string.
// String passw = new String(truePass, StandardCharsets.UTF_8);
// Log.d("body", lichaam);
// String[] opgebroken = lichaam.split("name=\"csrfmiddlewaretoken\" value=\"");
// String[] breukjes = opgebroken[1].split("\">");
// String middelToken = breukjes[0];
// String[] splitsing = lichaam.split("var csrf_token = '");
// String[] dilemma = splitsing[1].split("';");
// String csrf = dilemma[0];
// Log.d("tokens", "middel= " + middelToken);
// Log.d("tokens", "csrf= " + csrf);
// String gegevens = null;
// try {
// gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(middelToken, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
// } catch (UnsupportedEncodingException e) {
// throw new RuntimeException(e);
// }
//// android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
//// oven.setCookie("https://" + server, "csrftoken=" + csrf);
// myWebView.postUrl("https://" + server + "/login", gegevens.getBytes());
// }
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.
Thread draadje = new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("https://" + server + "/login");
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 {
pagina = new byte[30000];
ina.read(pagina);
}
try {
ina.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
String zooi = new String(pagina);
String[] opgebroken = zooi.split("name=\"csrfmiddlewaretoken\" value=\"");
String[] breukjes = opgebroken[1].split("\">");
String token = breukjes[0];
String gegevens = null;
String speculaas = "", THT = "";
List<HttpCookie> koektrommel = bakker.get(URI.create("https://" + server));
//Log.d("koek", koektrommel.toString());
for (int i = 0; i < koektrommel.size(); ++i) {
HttpCookie koekje = koektrommel.get(i);
if (Objects.equals(koekje.getName(), "csrftoken")) {
speculaas = koekje.toString();
THT = String.valueOf(koekje.getMaxAge());
//Log.d("domein", koekje.getDomain());
}
}
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);
}
String finalGegevens = gegevens;
//Log.d("token", speculaas);
String finalSpeculaas = speculaas;
String finalTHT = THT;
runOnUiThread(new Runnable() {
@Override
public void run() {
android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
oven.setCookie("https://" + server, finalSpeculaas + "; Max-Age=" + finalTHT + "; Path=/; SameSite=Lax; Secure");
myWebView.postUrl("https://" + server + "/login?next=/", finalGegevens.getBytes());
}
});
} finally {
urlConnection.disconnect();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
draadje.start();
//return token;
}
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
result -> {
@ -237,7 +430,7 @@ public class StartActivity extends AppCompatActivity {
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
public boolean onKeyUp(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
@ -245,7 +438,7 @@ public class StartActivity extends AppCompatActivity {
}
// 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)
return super.onKeyDown(keyCode, event);
return super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {

View File

@ -29,7 +29,7 @@
android:layout_marginStart="10dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="262dp"
android:hint="bookwyrm.social"
android:hint="e.g. bookwyrm.social"
android:inputType="text"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
@ -162,4 +162,4 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,9 @@
<?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

@ -0,0 +1,5 @@
* 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 40 KiB