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 + 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 36e6fab..0000000 Binary files a/build/intermediates/model_data.bin and /dev/null differ diff --git a/de.vanitasvitae.enigmandroid.txt b/de.vanitasvitae.enigmandroid.txt old mode 100644 new mode 100755 index 0876ffb..1d72d0c --- a/de.vanitasvitae.enigmandroid.txt +++ b/de.vanitasvitae.enigmandroid.txt @@ -1,15 +1,12 @@ Categories:Science & Education License:GPLv2 -Web Site: https://github.com/vanitasvitae/EnigmAndroid/wiki/EnigmAndroid -Source Code: https://github.com/vanitasvitae/EnigmAndroid -Issue Tracker: https://github.com/vanitasvitae/EnigmAndroid/issues -Summary: Simulation of the Enigma Machine +Web Site:https://github.com/vanitasvitae/EnigmAndroid/wiki/EnigmAndroid +Source Code:https://github.com/vanitasvitae/EnigmAndroid +Issue Tracker:https://github.com/vanitasvitae/EnigmAndroid/issues +Summary:Simulation of the Enigma Machine Description: -This is a simulation of the famous Enigma cipher machine used in the twentieth century and especially in the Second World War. -The Enigma Machine was a typewriter-like machine with 26 keys and corresponding lamps. It used a set of mechanical Rotors to achieve polyalphabetic substitution. - -The Enigma Machine was broken during the second world war by Marian Rejewski, Jerzy Różycki and Henryk Zygalski, who created a Machine called "Bomba" which could break the enigma code. -After Germany invaded Poland, the british mathematician Alan Turing (known for his work on theoretical computer science) succeeded in completely breaking the Enigma. +Simulation of the famous Enigma cipher machine used in the Second World War. +The Enigma Machine was a typewriter-like machine, which used a set of mechanical Rotors to achieve polyalphabetic substitution. Features: * Authentic Rotors @@ -17,7 +14,7 @@ Features: * Double Step Anomaly * Working plugboard -More Information about the historical Enigma can be found on https://de.wikipedia.org/wiki/Enigma_%28Maschine%29 +More Information about the historical Enigma can be found on [https://de.wikipedia.org/wiki/Enigma_%28Maschine%29 Wikipedia] . @@ -39,8 +36,13 @@ Build:0.1.2-24.02.2015-beta,8 subdir=app gradle=yes -Auto Update Mode:None -Update Check Mode:Tags -Current Version:0.1.2-24.02.2015-beta -Current Version Code:8 +Build:0.1.3-14.03.2015-beta,9 + commit=v0.1.3-14.03.2015-beta + subdir=app + gradle=yes + +Auto Update Mode:Version v%v +Update Check Mode:Tags +Current Version:0.1.3-14.03.2015-beta +Current Version Code:9 diff --git a/gradle.properties b/gradle.properties old mode 100644 new mode 100755 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar old mode 100644 new mode 100755 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties old mode 100644 new mode 100755 diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 diff --git a/local.properties b/local.properties deleted file mode 100644 index 5297dba..0000000 --- a/local.properties +++ /dev/null @@ -1,11 +0,0 @@ -## This file is automatically generated by Android Studio. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must *NOT* be checked into Version Control Systems, -# as it contains information specific to your local configuration. -# -# Location of the SDK. This is only used by Gradle. -# For customization when using a Version Control System, please read the -# header note. -#Thu Mar 12 23:34:48 CET 2015 -sdk.dir=/media/Daten/android-sdk-linux diff --git a/settings.gradle b/settings.gradle old mode 100644 new mode 100755