From 980b7e8c7d54558f2a1bf884f6ff071a6987e39b Mon Sep 17 00:00:00 2001 From: VanitasVitae Date: Sat, 15 Aug 2015 03:53:02 +0200 Subject: [PATCH] Updated to Version 0.1.4-15.08.2015 Rewrote major parts of the core, fixed layout issues, fixed anomaly, added send/receive functionality --- .../libraries/support_annotations_21_0_3.xml | 4 +- .idea/libraries/support_v4_21_0_3.xml | 2 +- CHANGELOG.txt | 7 + EnigmAndroid.iml | 8 +- License.md | 0 README.md | 0 app/app.iml | 25 +- .../de/vanitasvitae/enigmandroid/Enigma.java | 330 +++++------------- .../enigmandroid/MainActivity.java | 199 +++++++---- .../vanitasvitae/enigmandroid/Plugboard.java | 173 +++++---- .../de/vanitasvitae/enigmandroid/Rotor.java | 256 -------------- .../enigmandroid/SettingsActivity.java | 0 .../enigmandroid/rotors/Reflector.java | 93 +++++ .../enigmandroid/rotors/Rotor.java | 208 +++++++++++ .../main/res/drawable-hdpi/ic_launcher.png | Bin .../res/drawable-hdpi/ic_send_white_48dp.png | Bin 0 -> 446 bytes .../ic_send_white_48dp.png | Bin 0 -> 446 bytes .../ic_send_white_48dp.png | Bin 0 -> 352 bytes .../ic_send_white_48dp.png | Bin 0 -> 590 bytes .../ic_send_white_48dp.png | Bin 0 -> 798 bytes .../ic_send_white_48dp.png | Bin 0 -> 1131 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin .../res/drawable-mdpi/ic_send_white_48dp.png | Bin 0 -> 344 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin .../res/drawable-xhdpi/ic_send_white_48dp.png | Bin 0 -> 586 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin .../drawable-xxhdpi/ic_send_white_48dp.png | Bin 0 -> 806 bytes .../drawable-xxxhdpi/ic_send_white_48dp.png | Bin 0 -> 1136 bytes app/src/main/res/drawable/button.xml | 0 app/src/main/res/ic_launcher-web.png | Bin .../main/res/layout-land/activity_main.xml | 0 app/src/main/res/layout/activity_main.xml | 0 app/src/main/res/layout/dialog_about.xml | 4 +- .../main/res/layout/dialog_ringsettings.xml | 4 +- app/src/main/res/menu/main.xml | 7 +- .../res/values-de/about_dialog_resources.xml | 2 +- app/src/main/res/values-de/strings.xml | 60 +--- .../values-de/strings_activity_settings.xml | 0 app/src/main/res/values-w820dp/dimens.xml | 0 .../res/values/about_dialog_resources.xml | 0 app/src/main/res/values/dimens.xml | 0 app/src/main/res/values/strings.xml | 75 +--- .../res/values/strings_activity_settings.xml | 0 app/src/main/res/values/styles.xml | 0 app/src/main/res/xml/pref_page.xml | 0 build.gradle | 4 +- build/intermediates/dex-cache/cache.xml | 26 -- build/intermediates/model_data.bin | Bin 78996 -> 0 bytes de.vanitasvitae.enigmandroid.txt | 30 +- gradle.properties | 0 gradle/wrapper/gradle-wrapper.jar | Bin gradle/wrapper/gradle-wrapper.properties | 0 gradlew | 0 gradlew.bat | 0 local.properties | 11 - settings.gradle | 0 56 files changed, 696 insertions(+), 832 deletions(-) mode change 100644 => 100755 CHANGELOG.txt mode change 100644 => 100755 EnigmAndroid.iml mode change 100644 => 100755 License.md mode change 100644 => 100755 README.md mode change 100644 => 100755 app/src/main/java/de/vanitasvitae/enigmandroid/Enigma.java mode change 100644 => 100755 app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java delete mode 100644 app/src/main/java/de/vanitasvitae/enigmandroid/Rotor.java mode change 100644 => 100755 app/src/main/java/de/vanitasvitae/enigmandroid/SettingsActivity.java create mode 100644 app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Reflector.java create mode 100644 app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Rotor.java mode change 100644 => 100755 app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-hdpi/ic_send_white_48dp.png create mode 100644 app/src/main/res/drawable-ldrtl-hdpi/ic_send_white_48dp.png create mode 100644 app/src/main/res/drawable-ldrtl-mdpi/ic_send_white_48dp.png create mode 100644 app/src/main/res/drawable-ldrtl-xhdpi/ic_send_white_48dp.png create mode 100644 app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_white_48dp.png create mode 100644 app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_white_48dp.png mode change 100644 => 100755 app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-mdpi/ic_send_white_48dp.png mode change 100644 => 100755 app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_send_white_48dp.png mode change 100644 => 100755 app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_send_white_48dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_send_white_48dp.png mode change 100644 => 100755 app/src/main/res/drawable/button.xml mode change 100644 => 100755 app/src/main/res/ic_launcher-web.png mode change 100644 => 100755 app/src/main/res/layout-land/activity_main.xml mode change 100644 => 100755 app/src/main/res/layout/activity_main.xml mode change 100644 => 100755 app/src/main/res/layout/dialog_about.xml mode change 100644 => 100755 app/src/main/res/layout/dialog_ringsettings.xml mode change 100644 => 100755 app/src/main/res/menu/main.xml mode change 100644 => 100755 app/src/main/res/values-de/about_dialog_resources.xml mode change 100644 => 100755 app/src/main/res/values-de/strings.xml mode change 100644 => 100755 app/src/main/res/values-de/strings_activity_settings.xml mode change 100644 => 100755 app/src/main/res/values-w820dp/dimens.xml mode change 100644 => 100755 app/src/main/res/values/about_dialog_resources.xml mode change 100644 => 100755 app/src/main/res/values/dimens.xml mode change 100644 => 100755 app/src/main/res/values/strings.xml mode change 100644 => 100755 app/src/main/res/values/strings_activity_settings.xml mode change 100644 => 100755 app/src/main/res/values/styles.xml mode change 100644 => 100755 app/src/main/res/xml/pref_page.xml mode change 100644 => 100755 build.gradle delete mode 100644 build/intermediates/dex-cache/cache.xml delete mode 100644 build/intermediates/model_data.bin mode change 100644 => 100755 de.vanitasvitae.enigmandroid.txt mode change 100644 => 100755 gradle.properties mode change 100644 => 100755 gradle/wrapper/gradle-wrapper.jar mode change 100644 => 100755 gradle/wrapper/gradle-wrapper.properties mode change 100644 => 100755 gradlew mode change 100644 => 100755 gradlew.bat delete mode 100644 local.properties mode change 100644 => 100755 settings.gradle diff --git a/.idea/libraries/support_annotations_21_0_3.xml b/.idea/libraries/support_annotations_21_0_3.xml index 2b841e5..c88ae64 100644 --- a/.idea/libraries/support_annotations_21_0_3.xml +++ b/.idea/libraries/support_annotations_21_0_3.xml @@ -1,11 +1,11 @@ - + - + \ No newline at end of file diff --git a/.idea/libraries/support_v4_21_0_3.xml b/.idea/libraries/support_v4_21_0_3.xml index 58d5624..1f5aeb0 100644 --- a/.idea/libraries/support_v4_21_0_3.xml +++ b/.idea/libraries/support_v4_21_0_3.xml @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/CHANGELOG.txt b/CHANGELOG.txt old mode 100644 new mode 100755 index 7d6933b..62fdcf6 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,12 @@ CHANGELOG ENIGMANDROID +v0.1.4-15.08.2015< +*Rewrite of the core implementation to follow some principals of Software Engineering +*Fixed some layout issues +*Fixed anomaly for step by step inputs +*Added send/receive text functionality + + v0.1.3-14.03.2015< *Added About Dialog with ChangeLog-Button *Moved Version Info into About Dialog diff --git a/EnigmAndroid.iml b/EnigmAndroid.iml old mode 100644 new mode 100755 index 0bb6048..fb2763b --- a/EnigmAndroid.iml +++ b/EnigmAndroid.iml @@ -1,13 +1,14 @@ - + - + @@ -15,5 +16,4 @@ - - + \ No newline at end of file diff --git a/License.md b/License.md old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/app/app.iml b/app/app.iml index 2459d0c..c5beb38 100644 --- a/app/app.iml +++ b/app/app.iml @@ -1,5 +1,5 @@ - + @@ -13,8 +13,11 @@ - + @@ -33,13 +36,13 @@ - + - + @@ -68,6 +71,7 @@ + @@ -83,10 +87,9 @@ - + - - + + - - + \ No newline at end of file diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/Enigma.java b/app/src/main/java/de/vanitasvitae/enigmandroid/Enigma.java old mode 100644 new mode 100755 index 4b804ca..38e106b --- a/app/src/main/java/de/vanitasvitae/enigmandroid/Enigma.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/Enigma.java @@ -1,6 +1,9 @@ package de.vanitasvitae.enigmandroid; +import de.vanitasvitae.enigmandroid.rotors.Reflector; +import de.vanitasvitae.enigmandroid.rotors.Rotor; + /** * Enigma-machine *Copyright (C) 2015 Paul Schaub @@ -28,27 +31,31 @@ public class Enigma private Rotor r1; private Rotor r2; private Rotor r3; + //Slot for the reflector - private Rotor reflector; + private Reflector reflector; + + private boolean doAnomaly = false; + private boolean prefAnomaly; //Do you want to simulate the anomaly? - private boolean anomaly; //Is it time to spin twice? - //Standard configuration (rotors 1-3, reflector B, all three rotors set to position 1, rings too) - public static final int[] STANDARD_CONFIGURATION = {1, 2, 3, 2, 1, 1, 1, 0, 0, 0}; /** - * Create new Enigma with given configuration. - * If pbconf == null no plugs will be set (no scrambling in the plugboard). - * If conf == null the enigma will be set to STANDARD_CONFIGURATION. - * - * @param pbconf two-dimensional array containing the chars symbolizing plugs that need to be switched over. - * @param conf configuration of the enigma (a,b,c,d,e,f,g - a-c rotors, d reflector, e-g positions of the rotors) + * Create new Enigma with standard configuration. + * Empty Plugboard, rotors I,II,III, Positions 0,0,0 */ - public Enigma(char[][] pbconf, int[] conf) throws Plugboard.PlugAlreadyUsedException + public Enigma() { - if (conf != null) setConfiguration(conf); - else setConfiguration(Enigma.STANDARD_CONFIGURATION); + initialize(); + } - this.setPlugboard(pbconf); + private void initialize() + { + this.r1 = Rotor.createRotorI(0, 0); + this.r2 = Rotor.createRotorII(0, 0); + this.r3 = Rotor.createRotorIII(0, 0); + this.reflector = Reflector.createReflectorB(); + plugboard = new Plugboard(); + prefAnomaly = true; } /** @@ -60,16 +67,14 @@ public class Enigma public String encrypt(String w) { //output string - String c = ""; + String output = ""; //for each char x in k - for (int i = 0; i < w.length(); i++) + for (char x : w.toCharArray()) { - char x = w.charAt(i); - //encrypt char - c = c + this.encryptChar(x); + output = output + this.encryptChar(x); } //return en-/decrypted string - return c; + return output; } /** @@ -82,15 +87,15 @@ public class Enigma public char encryptChar(char k) { //Rotate rotors - r1.incrementCounter(); - if (r1.isAtTurnoverPosition() || (this.anomaly && prefAnomaly)) + r1.rotate(); + if (r1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly)) { - r2.incrementCounter(); + r2.rotate(); //Handle Anomaly - this.anomaly = r2.doubleTurnAnomaly(); + this.doAnomaly = r2.doubleTurnAnomaly(); if (r2.isAtTurnoverPosition()) { - r3.incrementCounter(); + r3.rotate(); } } int x = (int) k; @@ -99,27 +104,32 @@ public class Enigma //Encryption //forward direction x = plugboard.encrypt(x); - x = (x + r1.getCounter()) % 26; + x = normalize(x + r1.getRotation()); x = r1.encryptForward(x); - x = (x + r2.getCounter() - r1.getCounter()) % 26; + x = normalize(x + r2.getRotation() - r1.getRotation()); x = r2.encryptForward(x); - x = (x + r3.getCounter() - r2.getCounter()) % 26; + x = normalize(x + r3.getRotation() - r2.getRotation()); x = r3.encryptForward(x); - x = (26 + x - r3.getCounter()) % 26; + x = normalize(x - r3.getRotation()); //backward direction - x = reflector.encryptForward(x); - x = (26 + x + r3.getCounter()) % 26; + x = reflector.encrypt(x); + x = normalize(x + r3.getRotation()); x = r3.encryptBackward(x); - x = (26 + x - r3.getCounter() + r2.getCounter()) % 26; + x = normalize(x - r3.getRotation() + r2.getRotation()); x = r2.encryptBackward(x); - x = (26 + x - r2.getCounter() + r1.getCounter()) % 26; + x = normalize(x - r2.getRotation() + r1.getRotation()); x = r1.encryptBackward(x); - x = (26 + x - r1.getCounter()) % 26; + x = normalize(x - r1.getRotation()); x = plugboard.encrypt(x); return (char) (x + 65); //Add Offset } + public int normalize(int input) + { + return (26+input)%26; + } + /** * Prepare String for encryption via enigma * Replace . , ! ? : with X @@ -130,14 +140,13 @@ public class Enigma */ public static String prepare(String word) { - String w = word.toUpperCase(); - String c = ""; - for (int i = 0; i < w.length(); i++) + String input = word.toUpperCase(); + String output = ""; + for (char x : input.toCharArray()) { - char x = w.charAt(i); if (x >= 65 && x <= 90) //If x in [A..Z] { - c = c + x; //Append to String + output = output + x; //Append to String } //if x is special symbol else @@ -145,86 +154,11 @@ public class Enigma if (x == '.' || x == ',' || x == '!' || x == '?' || x == ':') { //replace x with X and encrypt - c = c + 'X'; + output = output + 'X'; } } } - return c; - } - - /** - * Create Plugboard configuration from String. - * String must be in format XY,AZ and so on. - * X and Y are plugs, that will be switched over. - * Don't use plugs twice such as in AA or AB,CA. This will cause Exceptions. - * - * @param p String - * @return Array containing plugboard configuration - */ - public static char[][] parsePlugs(String p) throws InvalidPlugboardConfigurationFormatException - { - p = p.toUpperCase(); - //Check, if empty - if (p.length() == 0) - { - return null; - } - //Ensure uppercase and split string - String[] in = p.toUpperCase().split(","); - - //Check, whether input have had a correct length. Length+1 divided by 3 should be exactly how much fields there are in the array. - //(2 chars or 2 chars followed by any times a comma and two chars) - if (in.length != (p.length() + 1) / 3) - { - throw new InvalidPlugboardConfigurationFormatException("Error parsing plugs! Maybe you missed a ','?"); - } else - { - //Create new 2 dimensional array for pairs of plugs - char[][] plugs = new char[(p.length() + 1) / 3][2]; - //Fill the array - int i = 0; - for (String x : in) - { - //Check, whether string is not representing a pair - if (x.length() != 2) - { - throw new InvalidPlugboardConfigurationFormatException("Error parsing plugs! Maybe you didn't enter a pair somewhere?"); - } - //If it does - else - { - char[] pair = x.toCharArray(); - //Check, if Plugs are in alphabet - if(pair[0]<65 || pair[1]<65 || pair[0]>90 || pair[1]>90) throw new InvalidPlugboardConfigurationFormatException("Error parsing plugs! Maybe you entered a number or a special character?"); - else - { - //add it to the array - plugs[i] = pair; - i++; - } - } - } - return plugs; - } - } - - /** - * Set the plugboard to a new created object and set the configuration - * - * @param c configuration - * @throws Plugboard.PlugAlreadyUsedException - */ - public void setPlugboard(char[][] c) throws Plugboard.PlugAlreadyUsedException - { - plugboard = new Plugboard(); - if (c != null) - { - //Set each plug pair - for (char[] x : c) - { - plugboard.setPlugPair(x[0], x[1]); - } - } + return output; } /** @@ -234,131 +168,41 @@ public class Enigma */ public void setConfiguration(int[] conf) { - if (conf.length != 10) + if (conf == null || conf.length != 10) { - setConfiguration(Enigma.STANDARD_CONFIGURATION); - } else + initialize(); + } + else { int ro1 = conf[0]; int ro2 = conf[1]; int ro3 = conf[2]; int ref = conf[3]; - int r1rot = 26 + conf[4] - 1; - int r2rot = 26 + conf[5] - 1; - int r3rot = 26 + conf[6] - 1; + int ro1rot = normalize(conf[4] - 1); + int ro2rot = normalize(conf[5] - 1); + int ro3rot = normalize(conf[6] - 1); int ro1Ring = conf[7]; int ro2Ring = conf[8]; int ro3Ring = conf[9]; - //Set first rotor - switch (ro1) - { - case 1: - { - r1 = new Rotor('1', (r1rot) % 26, ro1Ring); - break; - } - case 2: - { - r1 = new Rotor('2', (r1rot) % 26, ro1Ring); - break; - } - case 3: - { - r1 = new Rotor('3', (r1rot) % 26, ro1Ring); - break; - } - case 4: - { - r1 = new Rotor('4', (r1rot) % 26, ro1Ring); - break; - } - case 5: - { - r1 = new Rotor('5', (r1rot) % 26, ro1Ring); - break; - } - } - //Set second rotor - switch (ro2) - { - case 1: - { - r2 = new Rotor('1', (r2rot) % 26, ro2Ring); - break; - } - case 2: - { - r2 = new Rotor('2', (r2rot) % 26, ro2Ring); - break; - } - case 3: - { - r2 = new Rotor('3', (r2rot) % 26, ro2Ring); - break; - } - case 4: - { - r2 = new Rotor('4', (r2rot) % 26, ro2Ring); - break; - } - case 5: - { - r2 = new Rotor('5', (r2rot) % 26, ro2Ring); - break; - } - } - //Set third rotor - switch (ro3) - { - case 1: - { - r3 = new Rotor('1', (r3rot) % 26, ro3Ring); - break; - } - case 2: - { - r3 = new Rotor('2', (r3rot) % 26, ro3Ring); - break; - } - case 3: - { - r3 = new Rotor('3', (r3rot) % 26, ro3Ring); - break; - } - case 4: - { - r3 = new Rotor('4', (r3rot) % 26, ro3Ring); - break; - } - case 5: - { - r3 = new Rotor('5', (r3rot) % 26, ro3Ring); - break; - } - } + //Set rotors + r1 = Rotor.createRotor(ro1, ro1Ring, ro1rot); + r2 = Rotor.createRotor(ro2, ro2Ring, ro2rot); + r3 = Rotor.createRotor(ro3, ro3Ring, ro3rot); + //Set reflector - switch (ref) - { - case 1: - { - reflector = new Rotor('A', 0, 0); - break; - } - case 2: - { - reflector = new Rotor('B', 0, 0); - break; - } - case 3: - { - reflector = new Rotor('C', 0, 0); - break; - } - } + reflector = Reflector.createReflector(ref); + + //catch double turn anomaly on step by step basis + this.doAnomaly = r2.doubleTurnAnomaly(); } } + public void setPlugboard(Plugboard p) + { + this.plugboard = p; + } + /** * Return the configuration, the enigma machine is in right NOW * @@ -366,32 +210,24 @@ public class Enigma */ public int[] getConfiguration() { - int[] c = new int[10]; + int[] configuration = new int[10]; { - c[0] = r1.getType(); - c[1] = r2.getType(); - c[2] = r3.getType(); - c[3] = reflector.getType(); - c[4] = r1.getCounter(); - c[5] = r2.getCounter(); - c[6] = r3.getCounter(); - c[7] = r1.getRingsetting(); - c[8] = r2.getRingsetting(); - c[9] = r3.getRingsetting(); + configuration[0] = r1.getType(); + configuration[1] = r2.getType(); + configuration[2] = r3.getType(); + configuration[3] = reflector.getType(); + configuration[4] = r1.getRotation(); + configuration[5] = r2.getRotation(); + configuration[6] = r3.getRotation(); + configuration[7] = r1.getRingSetting(); + configuration[8] = r2.getRingSetting(); + configuration[9] = r3.getRingSetting(); } - return c; + return configuration; } public void setPrefAnomaly(boolean b) { this.prefAnomaly = b; } - - public static class InvalidPlugboardConfigurationFormatException extends Exception - { - public InvalidPlugboardConfigurationFormatException(String m) - { - super(m); - } - } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java b/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java old mode 100644 new mode 100755 index 04f61c7..407ab4e --- a/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java @@ -36,13 +36,15 @@ import android.widget.Toast; public class MainActivity extends Activity { + private Menu menu; private Spinner rotor1; private Spinner rotor2; private Spinner rotor3; - private Spinner reversingRotor; + private Spinner reflector; private Spinner rotor1Position; private Spinner rotor2Position; private Spinner rotor3Position; + private EditText plugboard; private EditText input; private EditText output; @@ -51,9 +53,9 @@ public class MainActivity extends Activity private static final String URI_CHANGELOG = "https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt"; private Enigma enigma; - //memory for the ringsettings - private int[] ringsettings = {0,0,0}; - private boolean anomaly = true; + //memory for the ringSettings + private int[] ringSettings = {0,0,0}; + private boolean prefAnomaly; @Override public void onCreate(Bundle savedInstanceState) @@ -61,13 +63,32 @@ public class MainActivity extends Activity super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_main); this.initLayout(); - this.reset(); + this.prefAnomaly = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("prefAnomaly", true); + this.resetLayout(); + ActivitySingleton singleton = ActivitySingleton.getInstance(); + singleton.setActivity(this); + //Handle shared text + Intent intent = getIntent(); + String action = intent.getAction(); + String type = intent.getType(); + + if (Intent.ACTION_SEND.equals(action) && type != null) { + if ("text/plain".equals(type)) + { + String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); + if (sharedText != null) + { + input.setText(sharedText); + } + } + } } @Override public boolean onCreateOptionsMenu(Menu menu) { + this.menu = menu; this.getMenuInflater().inflate(R.menu.main, menu); return true; } @@ -81,7 +102,7 @@ public class MainActivity extends Activity int id = item.getItemId(); if (id == R.id.action_reset) { - this.reset(); + this.resetLayout(); Toast.makeText(getApplicationContext(), R.string.message_reset, Toast.LENGTH_SHORT).show(); return true; @@ -101,6 +122,21 @@ public class MainActivity extends Activity showAboutDialog(); return true; } + else if (id == R.id.action_send) + { + if(output.getText().length() == 0) + { + Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_LONG).show(); + } + else + { + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, output.getText().toString()); + sendIntent.setType("text/plain"); + startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to))); + } + } return super.onOptionsItemSelected(item); } @@ -115,76 +151,56 @@ public class MainActivity extends Activity conf[0] = rotor1.getSelectedItemPosition() + 1; conf[1] = rotor2.getSelectedItemPosition() + 1; conf[2] = rotor3.getSelectedItemPosition() + 1; - conf[3] = reversingRotor.getSelectedItemPosition() + 1; + conf[3] = reflector.getSelectedItemPosition() + 1; conf[4] = rotor1Position.getSelectedItemPosition() + 1; conf[5] = rotor2Position.getSelectedItemPosition() + 1; conf[6] = rotor3Position.getSelectedItemPosition() + 1; - conf[7] = ringsettings[0]; - conf[8] = ringsettings[1]; - conf[9] = ringsettings[2]; + conf[7] = ringSettings[0]; + conf[8] = ringSettings[1]; + conf[9] = ringSettings[2]; - try - { - enigma = new Enigma(null, null); - } catch (Plugboard.PlugAlreadyUsedException e) - { - //There is nothing that could possibly go wrong here. - } + enigma = new Enigma(); - char[][] plugboardConfiguration = null; - try - { - plugboardConfiguration = Enigma.parsePlugs(plugboard.getText().toString()); - } catch (Enigma.InvalidPlugboardConfigurationFormatException e) - { - String error = this.getResources().getString(R.string.error_parsing_plugs) + ": " + e.getMessage(); - Toast.makeText(getApplicationContext(), error, - Toast.LENGTH_LONG).show(); - } - try - { - enigma.setConfiguration(conf); - enigma.setPlugboard(plugboardConfiguration); - enigma.setPrefAnomaly(anomaly); - - } catch (Plugboard.PlugAlreadyUsedException e) - { - Toast.makeText(this.getApplicationContext(), e.getMessage(), - Toast.LENGTH_LONG).show(); - } + int[][] plugboardConfiguration = null; + plugboard.setText(plugboard.getText().toString().toUpperCase()); + plugboardConfiguration = Plugboard.parseConfigurationString(plugboard.getText().toString()); + enigma.setConfiguration(conf); + enigma.setPlugboard(new Plugboard(plugboardConfiguration)); + enigma.setPrefAnomaly(prefAnomaly); } /** - * Set the chosen Configuration to the enigma, get the input string from the input textbox and prepare it, - * set the input to the prepared text, encrypt the prepared input and set the encrypted string to the - * output textbox and update the spinners to their new positions. + * Set the chosen Configuration to the enigma, get the input string from the input textbox and + * prepare it, set the input to the prepared text, encrypt the prepared input and set the + * encrypted string to the output textbox and update the spinners to their new positions. * @param v View */ public void doCrypto(View v) { - updateEnigma(null); - String m = input.getText().toString(); - m = Enigma.prepare(m); - input.setText(m); - output.setText(enigma.encrypt(m)); - updateSpinner(enigma.getConfiguration()); - + if(input.getText().length()!=0) { + updateEnigma(null); + String m = input.getText().toString(); + m = Enigma.prepare(m); + input.setText(m); + output.setText(enigma.encrypt(m)); + updateSpinner(enigma.getConfiguration()); + } } /** * Reset all the spinners and textboxes and the ringsettings memory */ - private void reset() + private void resetLayout() { rotor1.setSelection(0); rotor2.setSelection(1); rotor3.setSelection(2); - reversingRotor.setSelection(1); + reflector.setSelection(1); rotor1Position.setSelection(0); rotor2Position.setSelection(0); rotor3Position.setSelection(0); - ringsettings = new int[]{0,0,0}; + ringSettings = new int[]{0,0,0}; plugboard.setText(""); input.setText(""); output.setText(""); @@ -195,6 +211,9 @@ public class MainActivity extends Activity */ private void initLayout() { + Character[] charArray = new Character[26]; + for(int i=0; i<26; i++) {charArray[i] = (char) (65+i);} + rotor1 = (Spinner) findViewById(R.id.rotor1); ArrayAdapter rotor1Adapter = ArrayAdapter.createFromResource(this, R.array.enigma_rotors, android.R.layout.simple_spinner_item); @@ -214,31 +233,40 @@ public class MainActivity extends Activity rotor3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); rotor3.setAdapter(rotor3Adapter); - reversingRotor = (Spinner) findViewById(R.id.reflector); + reflector = (Spinner) findViewById(R.id.reflector); ArrayAdapter relfectorAdapter = ArrayAdapter.createFromResource(this, R.array.enigma_reflectors, android.R.layout.simple_spinner_item); relfectorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - reversingRotor.setAdapter(relfectorAdapter); + reflector.setAdapter(relfectorAdapter); rotor1Position = (Spinner) findViewById(R.id.rotor1position); - ArrayAdapter rotor1PositionAdapter = ArrayAdapter.createFromResource(this, - R.array.rotor_positions, android.R.layout.simple_spinner_item); + ArrayAdapter rotor1PositionAdapter = new ArrayAdapter<>(this.getApplicationContext(), + android.R.layout.simple_spinner_item,charArray); rotor1PositionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); rotor1Position.setAdapter(rotor1PositionAdapter); rotor2Position = (Spinner) findViewById(R.id.rotor2position); - ArrayAdapter rotor2PositionAdapter = ArrayAdapter.createFromResource(this, - R.array.rotor_positions, android.R.layout.simple_spinner_item); + ArrayAdapter rotor2PositionAdapter = new ArrayAdapter<>(this.getApplicationContext(), + android.R.layout.simple_spinner_item,charArray); rotor2PositionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); rotor2Position.setAdapter(rotor2PositionAdapter); rotor3Position = (Spinner) findViewById(R.id.rotor3position); - ArrayAdapter rotor3PositionAdapter = ArrayAdapter.createFromResource(this, - R.array.rotor_positions, android.R.layout.simple_spinner_item); + ArrayAdapter rotor3PositionAdapter = new ArrayAdapter<>(this.getApplicationContext(), + android.R.layout.simple_spinner_item,charArray); rotor3PositionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); rotor3Position.setAdapter(rotor3PositionAdapter); plugboard = (EditText) findViewById(R.id.plugboard); + plugboard.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if(!hasFocus) + { + plugboard.setText(plugboard.getText().toString().toUpperCase()); + } + } + }); input = (EditText) findViewById(R.id.input); output = (EditText) findViewById(R.id.output); @@ -260,29 +288,36 @@ public class MainActivity extends Activity } /** - * Show the dialog where the user can pick the ringsettings and set them if the user doesn't abort. + * Show the dialog where the user can pick the ringsettings and set them if the user doesn't + * abort. */ public void showRingsettingsDialog() { View ringsettingsView = View.inflate(this, R.layout.dialog_ringsettings, null); + Integer[] ringArray = new Integer[26]; + for(int i=1; i<=26; i++) {ringArray[i-1] = i;} + final Spinner ring1 = (Spinner) ringsettingsView.findViewById(R.id.rotor1ring); - ArrayAdapter ring1Adapter = ArrayAdapter.createFromResource(this, R.array.ring_positions, android.R.layout.simple_spinner_item); + ArrayAdapter ring1Adapter = new ArrayAdapter<>(this.getApplicationContext(), + android.R.layout.simple_spinner_item,ringArray); ring1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); ring1.setAdapter(ring1Adapter); - ring1.setSelection(ringsettings[0]); + ring1.setSelection(ringSettings[0]); final Spinner ring2 = (Spinner) ringsettingsView.findViewById(R.id.rotor2ring); - ArrayAdapter ring2Adapter = ArrayAdapter.createFromResource(this, R.array.ring_positions, android.R.layout.simple_spinner_item); + ArrayAdapter ring2Adapter = new ArrayAdapter<>(this.getApplicationContext(), + android.R.layout.simple_spinner_item,ringArray); ring2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); ring2.setAdapter(ring2Adapter); - ring2.setSelection(ringsettings[1]); + ring2.setSelection(ringSettings[1]); final Spinner ring3 = (Spinner) ringsettingsView.findViewById(R.id.rotor3ring); - ArrayAdapter ring3Adapter = ArrayAdapter.createFromResource(this, R.array.ring_positions, android.R.layout.simple_spinner_item); + ArrayAdapter ring3Adapter = new ArrayAdapter<>(this.getApplicationContext(), + android.R.layout.simple_spinner_item,ringArray); ring3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); ring3.setAdapter(ring3Adapter); - ring3.setSelection(ringsettings[2]); + ring3.setSelection(ringSettings[2]); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.title_ringsetting); @@ -292,8 +327,10 @@ public class MainActivity extends Activity { public void onClick(DialogInterface dialog, int id) { - ringsettings = new int[]{ring1.getSelectedItemPosition(), ring2.getSelectedItemPosition(), ring3.getSelectedItemPosition()}; - String message = getResources().getString(R.string.dialog_ringsettings_success) + " " + (ringsettings[2]+1) + ", " + (ringsettings[1]+1) + ", " + (ringsettings[0]+1) + "."; + ringSettings = new int[]{ring1.getSelectedItemPosition(), + ring2.getSelectedItemPosition(), ring3.getSelectedItemPosition()}; + String message = getResources().getString(R.string.dialog_ringsettings_success) + " " + (ringSettings[2]+1) + ", " + + (ringSettings[1]+1) + ", " + (ringSettings[0]+1) + "."; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); } @@ -341,7 +378,7 @@ public class MainActivity extends Activity case RESULT_SETTINGS: { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); - this.anomaly = sharedPrefs.getBoolean("prefAnomaly", true); + this.prefAnomaly = sharedPrefs.getBoolean("prefAnomaly", true); break; } } @@ -354,4 +391,28 @@ public class MainActivity extends Activity startActivity(intent); } } + + public static class ActivitySingleton + { + private static ActivitySingleton instance = null; + private Activity activity; + + private ActivitySingleton(){} + public static ActivitySingleton getInstance() + { + if(instance == null) instance = new ActivitySingleton(); + return instance; + } + + public void setActivity(Activity activity) + { + this.activity = activity; + } + + public Activity getActivity() + { + return activity; + } + + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java b/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java index 709a581..3938d84 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java @@ -1,102 +1,145 @@ package de.vanitasvitae.enigmandroid; +import android.app.Activity; +import android.widget.Toast; + +import java.util.ArrayList; + /** - * Class representing the plugboard - *Copyright (C) 2015 Paul Schaub - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * @author vanitasvitae + * Created by vanitas on 12.08.15. */ public class Plugboard { - //Plugboard - // Q W E R T Z U I O - // A S D F G H J K - // P Y X C V B N M L + Integer[] plugs; - //Array containing plugged pairs - int[] pb; - //Standard array to compare pb to. - public static final int[] ref = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; - - /** - * Create new plugboard without any plugged pairs. (empty, no scrambling here) - */ public Plugboard() { - pb = new int[26]; - resetPlugboard(); + plugs = new Integer[26]; + } + + public Plugboard(int[][] configuration) + { + setConfiguration(configuration); + } + + public Plugboard(String configuration) + { + setConfiguration(parseConfigurationString(configuration)); } /** - * En-/decrypt a char following the connections on the plugboard + * Configure the plugboard according to the given array. * - * @param x char to perform crypto on - * @return en-/decrypted char + * @param configuration */ - public int encrypt(int x) + public void setConfiguration(int[][] configuration) { - return pb[x]; + if(configuration != null) { + boolean validConfiguration = true; + plugs = new Integer[26]; + for (int[] p : configuration) { + if (!setPlugs(p[0], p[1])) { + validConfiguration = false; + break; + } + } + if (!validConfiguration) plugs = new Integer[26]; + } + else plugs = new Integer[26]; } /** - * Reset the plugboard (no plugged pairs) + * Parse configuration from input string + * input must have the following form: "" or "XY" or "XY,VW" or "XY,...,AB" + * A character must not be inside the input multiple times. Exception is ',' + * This is not catched here! + * @param input String that codes the configuration + * @return two dimensional array of plugged symbols */ - public void resetPlugboard() + public static int[][] parseConfigurationString(String input) { - pb = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; + Activity activity = MainActivity.ActivitySingleton.getInstance().getActivity(); + //If length != 0,2,5,8... ( ,XY, XY-VW, ...) + if(((input.length()+1)%3)!=0&&input.length()!=0) + { + Toast.makeText(activity.getApplicationContext(), R.string.error_parsing_plugs, + Toast.LENGTH_LONG).show(); + return null; + } + else { + input = input.toUpperCase(); + ArrayList plugList = new ArrayList(); + int[] plug = new int[2]; + for (int i = 0; i < input.length(); i++) { + int c = input.charAt(i) - 65; + if (c < 0 || c > 25) { + if (i % 3 != 2) { + Toast.makeText(activity.getApplicationContext(), R.string.error_parsing_plugs, + Toast.LENGTH_LONG).show(); + return null; + } + } else { + if (i % 3 == 0) { + plug = new int[2]; + plug[0] = c; + } + if (i % 3 == 1) { + plug[1] = c; + plugList.add(plug); + } + + } + } + int[][] parsedConfiguration = new int[plugList.size()][2]; + for(int i=0; i^MovOQy2%69g!l`1nlRu9q5pvE zX@myYNfB_YP>O(!La_r*Bos5CgHW7+xT6~oU$g=ef(baElh82WwP-+Oc&05B5IJN5 zB1?EcGzbZZ7QO+|!~|S(6`Ez4Z4SBMo;QAS3pm9ho9xr!mKQ!VTYnjTO4rC9j|;f3SF@(pKOI4j=1E3cc)~>%*CI9?W5jhI{pl# zB8ki(Y+Z@Yz#eJxok#U>^@^m0@8+i>;}%I($V3X;e=~@rA`}uySSUP_ppeEjA|O&b zm&b-m^(N!^U}YjHKUfWtNAeJ=)UTTkLOu0J4no~1k!nKyNvNc!~$75AJC z{Bl0x<*Le*DO09QtA-A1TvL5*MZWE^M-9BU0W{AkuK@W$qew&2$q4GPOAXKl&>)HA zf`mxl=fejDB6%Pok_QqZ2_P$y1o9&VCI$JC@`Jibr0k#pCrPBNpbo3tAdCPKA_*WN zk^mAS2_QL=59$k%1W=Qa-ni$2LpE7rhKT@3kMzVXXY8}i0#l6re1upe;Rex-N78N( z2X)!u@n1I(HjVV6-9P}%ar`UjnLExoV1q@bn+A<`lI=ewd*G5IwpeD?O_uIBD}f*C z==}sxJfLvDI4J%*=iD#;ry~$hxL+J(1@u2Z! o7eIQzD-q;x0ToaI6;ST|1o-RvuW?C35dZ)H07*qoM6N<$f>2Jlvj6}9 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-ldrtl-mdpi/ic_send_white_48dp.png b/app/src/main/res/drawable-ldrtl-mdpi/ic_send_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..4735a7d71186c6c3762b44d2e6686dc793d9e7cf GIT binary patch literal 352 zcmV-m0iXVfP)c)f~kIRddy&k<*_Najm@&Oh&Jt#p7>-Ipu8(Q1JDaQT7JRh-~a#s07*qoM6N<$f^nArkN^Mx literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_white_48dp.png b/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a16ec5c3ae986cc382404102d9bafee38b090cce GIT binary patch literal 798 zcmV+(1L6FMP)6i$6Ac7-+@J0wnfP_7PBS41PBsc=ZtmX(1k=fWsfE42ZA{Ng8kD#6W zni-XYHpMU3`)=@5Ppx0w+dUzK5JCtcgb+dqA%qZUxW+qrlds4AzN0)~3-}g6<9C`B zMzlmwaSd15V221Q@5oM6CEp{cjp|h!RRpQ1BB+S!K3hyAf|lB-BtQIuj8R39h$@0q zRGOcDLDr}uXfQph2wLLhDXr{8LzOc>;54p}6j&XqAZq6N*e!R?+zPWfG)=^Y6p4INzl`_h8M&FSF$`*I4>!TI;)6=ZnZ`}d^i< zRKWp?;QYiH!2yck0QGM(fDQy_9O^a>H4F|=|C4Vda~~X_9$^5~!2#;vtfr{xRzMvb zpjcaB!BPhYD7Jh6>fk;=n@vL&O?GgAIygWboOQ_^9H7|Q2`Cm+TKXUFngr+Y$m8(H zA~--9oa09w9H73y0jLin0qWo!f$Td{fI2upeRk^w)DI9KK!5-N0tCnd1PBlyK!5-N c@&MKQ0V-K!@wO@@-~a#s07*qoM6N<$f({&EsQ>@~ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_white_48dp.png b/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..e949db749312e6d0ada593b00c2aab2d0bbec925 GIT binary patch literal 1131 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE1xWt5x}=AJfyKzv#WAFU@$FpiqA8&aZq*Ao zd1O5~3@)fM^Bi}U||K@2c4y>)NRfmEyi`}y(&tdF>cHHNZox&Qjl0ksCE zsQ2?<{5dmu%~s)rlC%iM00%QGt_+#En$vE~DrM!#V?X^uV?l0--qeeM4y)g4F1p-p zUCJsk_oWd~)plXm5)pw;zyEjEsvdZup&&4~au)+vhWuP(ouKAwt{3I(GoG0_cr{#H zd9s%EO21!R1JIDQviggH=d*LIke6i*={VP_WW{yDWjQ0i=!cXNzs(MfOqYO)nthGj zr}OleZEv`E49FFn`}q!2fP zFxSLcIiaUmN7#{ZA;{aZKvPyQEWZ3yyzYs&-80>|hppe3+$>IpmI-Iar1weMJ>iXe zWNG#H%!@1bj};l+e@^2)U$NiV%Jh7N!vTr;8{bHt=dcKJIc|K<%|TEWB)Ct>YTn0X zOno1CrRRNYX%M{kv@3njzh9kw={5=v3M7GQ-hS-^aT4Uyf1WkIm*n4n?(rST@B`U3 zwgHTQ-ko&TfDzhZW{?}f?L^U8M|YWP?;rT=X6lfN4B ztN+eE@jLLpyC5^?r0 zdlmMtxHXzerpi^=YjLdj|Jv)l`_C8goTmHbpDuP>RbYRK>DRBtxF@7v z49!!-5+?8j+eZKZ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png old mode 100644 new mode 100755 diff --git a/app/src/main/res/drawable-mdpi/ic_send_white_48dp.png b/app/src/main/res/drawable-mdpi/ic_send_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..ef59e77678dbd3f5d866bca9058b6e90cb8d6098 GIT binary patch literal 344 zcmV-e0jK_nP)&W`22C;JryNwK41(MIA#GvFb#~s zwsao25E&6n03w(GL@)`A!D$_85` z%9!`-s3_@X0OI`y_5>OaJWhc7Ux1pxX-=Z&t1o;=Bq}NC$3*rSV}~5rah@Eqct#)^ z#sARKe>b^SMWD8;A|0im5z9_QQGnQ=9+)gN{ZC&+5rBvy01-u99ZM?OT$kUFh@ye? qUBLr0?$ZKzW0Q{J0Y5k327Cd{Pq+sr^Mm~W0000iiyj@9(xVOVg#(7p003K_Gj#>nXC*>~ z2iWpwKJ$p7Er1B+1Rz;*lb$1h2o)J%M>$)bF?9w|p{xKzs8|5sDMy8xSOSPpT{8g5 znuiPw03r#cM?d%dGk^-^0w6*?WzsCbPb2|^Y6(Duas&{e0sur3N{^b!ng=Cx8fL2p~fB9RWlrPXH0B4&V$IxXN9QdBq2I(S<5~;1uV$%xw;N!HTa93iX6> zJwV&@S#X1H4M2eTh)@*(jm}4e8dU%UnU4rn28cJGPt5680EC#&=C@E00M2uTI~?(n z_k8;+fX7^FN1=;c;~pox=Hovrbf2@TP>>!Mvfw(W^-CP6$7N}>LiM=(yQ3AL#|3FB zA0?`LTp`VfPPtm@aakJIKQ#KdU<05JY(@YojR$~8V*nu1_+Bl}8TelAsx&45de>kA zp!d-R03wa+OFosx13;uP01#X7fJkEiAS(mD zi?1q;4S-5x1E8C59snYZ0l=obUhDy&(ij2gMzj&Y81KIqEP)97a=+)GGgoibr515hag6BT(rQ$s^Dr1(nM`!BU(m#V32n zaegQJTf00dGHbq-%$eOV#u#IaF~%5Uj4{TTe}~sxrbQ$7qaS?%=G^6=1t~!VOGccq zAT6k1#--KZEa)q%6v1^YNDC^0doF^rAQ7Ae3Fh3Ple3_2tRRCMSdc&jXF)o+yaatm z@E5^ZkP6O%bZ`eOXkBp67;LkkT{gj#i?l2#F*pm-EJScM7PLT9MsOA+g0mnI+;I!q zis1C4CI5qu+!n!EkOy;~LA4fRNH6HMiw=8oFF7<`{0D?m8O9U4{Q0RTVXUI+f zL814xTLiZ~f(~Ju~#xvtpv6vLJm|@w>e{wgC`^0U)>+yRa-Zj6)p?>X)q4r)+T2 zcd-qq|8oH9sC?q=r~q|TfI2Eb@r}hW%OEP_P^WRIji`)d=Kpy>85N)&DF75vSxpg9 z0qRLqKoOM%OTB&qP(%f2zL5jaol#jd*;|1CbyR>lD(jLvDnJ<(px&3A0g7uGfa1Urpm!D(puYJ8XmwP8))i;40C@rA0RjXF5FkK+ k0C|7_0RjXF5FkL_2YayDe7#r6G5`Po07*qoM6N<$f;n$jyZ`_I literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_send_white_48dp.png b/app/src/main/res/drawable-xxxhdpi/ic_send_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..30f8b26115658b892483c5b74184281dc6055a08 GIT binary patch literal 1136 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE1xWt5x}=AJfyLa@#WAFU@$Fp8pf{ls?$!ZP zPRcWxW1FU(nejr%Byh^XOR5=ad^QQ3Qq~H++5ut=Hf-VxRw{g6QKD?$96c?{^}6Wn z_y0G?&;PvC<@=rLd#l^_Z3h{T3f8uVeeJUfNlH@tuiQR~Z|jOWvD2ywg^TmQ8gYm1 zX;A(Q3W^O1rV0y|Sv+dK(#udjVH!}@y#MRA zQ)jgvxbcE4UXkT__^jH4^1JdtH}O>ea=FW);8DrA>+0mQZTEsC89%XeGQLx&UAyrA zVg}}C3R@KqoL*-aCe9S4;=yqODECjnlGSFh_?KDtuBZRREX+r zt(?T%Ux(%R|JD2F-FWPHvGbQklkL3za}8eq>ux+=c=05Ewau5uZGSc#ceXD$&0oDo zu*_8Yvv=jUig{l}=DM}p%Kged4wC&Zq+$Q&zlT?2H%R9IZFMr{D0RAaU~lI+6Vhi<%j}%SKMi*6!qEn)6+ysC1*c z6^F+~$!DMP76o5n=8N&~X_)oWE{0{viyLwuA4;zFDG^BM02%tw(0`GzLc{in0u$zG zKk+PHlq_(7d!iU)xXW>!26xM|OdWmU2bOlF#}}`Ap^)G`IjdZUl_@Lg+6u4#GAuD7 zVsqop3jxK0XTDH4ATG-?r``4WL~SdM8{dG=)U-<0`CZF0XXfH&hWrwNf>%IqbodE# z-MIF}87Qs(U(rg`zeHfdqRYoORj~-n6<|Dms(5kNu}Gi(2IjN77d1D?E)v#%u)?n- zj0fm@YoM_geKuZnJh0H-io@bU)2~RK{)W)AE1FwBaV7{fFt9Ol5T?$W)iVT56Vu7< R^5X~Pb5B=4mvv4FO#s%V&n*A| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/button.xml b/app/src/main/res/drawable/button.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/ic_launcher-web.png b/app/src/main/res/ic_launcher-web.png old mode 100644 new mode 100755 diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/layout/dialog_about.xml b/app/src/main/res/layout/dialog_about.xml old mode 100644 new mode 100755 index 84cdf9e..eca25ca --- a/app/src/main/res/layout/dialog_about.xml +++ b/app/src/main/res/layout/dialog_about.xml @@ -1,7 +1,9 @@ + android:layout_height="wrap_content" + android:paddingStart="5dp" + android:paddingEnd="5dp"> + android:layout_height="wrap_content" + android:paddingStart="5dp" + android:paddingEnd="5dp"> + Bedienungsanleitung Um einen Text mit EnigmAndroid zu ver- oder entschlüsseln, tippen Sie den Klar- oder Geheimtext in das Feld \"Hier tippen\". - Wählen Sie anschließend eine Umkehrwalze, und Walzen für die Plätze 1 bis 3 aus. Legen Sie außerdem die Startpositionen der Walzen fest. + Wählen Sie anschließend eine Umkehrwalze, sowie Walzen für die Plätze 1 bis 3 aus. Legen Sie außerdem die Startpositionen der Walzen fest. Zuletzt können Sie noch einige Steckerpaare auf dem Steckbrett festlegen. Tippen Sie dazu die gewünschten Paare mit Komma getrennt in das entsprechende Textfeld (zb. \"ab,cd\"). Beachten Sie, dass Sie einen Stecker nicht doppelt nutzen dürfen. Optional können Sie auch noch die Ringstellung definieren. Öffnen Sie dazu das Optionsmenü und wählen Sie den Punkt \"Ringstellung\". diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml old mode 100644 new mode 100755 index 8bd8f50..29cd319 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -6,6 +6,8 @@ Zurücksetzen Einstellungen Ringstellung + Senden + Senden an… Wähle die Ringstellungen für die Walzen: Hier Tippen Enigma-Code @@ -21,6 +23,7 @@ Fehler: Fehlerhafte Steckerbrettkonfiguration. Kann Stecker nicht setzen: Fehler: Einer oder mehrere dieser Stecker sind bereits in Benutzung: + Nachricht ist leer. Ringstellungen OK Abbrechen @@ -35,66 +38,11 @@ IV V + A B C - - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - 21 - 22 - 23 - 24 - 25 - 26 - diff --git a/app/src/main/res/values-de/strings_activity_settings.xml b/app/src/main/res/values-de/strings_activity_settings.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/values/about_dialog_resources.xml b/app/src/main/res/values/about_dialog_resources.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml old mode 100644 new mode 100755 index a95d2ec..479b5e1 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,13 +1,15 @@ - 0.1.3-14.03.2015 + 0.1.4-15.08.2015 EnigmAndroid Version Reset - Ringsettings + Ring-Settings Settings - Choose ringsettings for the rotors: + Send + Send to… + Choose ring-settings for the rotors: Type here EnigmaCode Plugboard (AZ,BE...) @@ -15,13 +17,14 @@ Rotor 2 Rotor 3 Reflector - Position Rotor 1 - Position Rotor 2 - Position Rotor 3 + Position\nRotor 1 + Position\nRotor 2 + Position\nRotor 3 En-/Decrypt! - Error: Can\'t interpret Plugboard Input. + Error: Can\'t interpret plugboard input. Unable to plug - Error: One or more of these Plugs are already in use: + Error: One or more of these plugs are already in use: + Can\'t send empty text. Ringsettings OK Cancel @@ -41,60 +44,4 @@ B C - - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - 21 - 22 - 23 - 24 - 25 - 26 - diff --git a/app/src/main/res/values/strings_activity_settings.xml b/app/src/main/res/values/strings_activity_settings.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml old mode 100644 new mode 100755 diff --git a/app/src/main/res/xml/pref_page.xml b/app/src/main/res/xml/pref_page.xml old mode 100644 new mode 100755 diff --git a/build.gradle b/build.gradle old mode 100644 new mode 100755 index d3ff69d..9acae59 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,11 @@ -// 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. buildscript { repositories { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.1.0' + classpath 'com.android.tools.build:gradle:1.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/build/intermediates/dex-cache/cache.xml b/build/intermediates/dex-cache/cache.xml deleted file mode 100644 index a32e652..0000000 --- a/build/intermediates/dex-cache/cache.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - diff --git a/build/intermediates/model_data.bin b/build/intermediates/model_data.bin deleted file mode 100644 index 36e6fabff5baf99e86eb6b8a9872d020a67d4107..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78996 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