diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index cbaec62..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -EnigmAndroid \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 217af47..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/dictionaries/vanitas.xml b/.idea/dictionaries/vanitas.xml deleted file mode 100644 index aba6d8c..0000000 --- a/.idea/dictionaries/vanitas.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - plugboard - ringsetting - ringsettings - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index e206d70..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index fe865d3..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/.idea/libraries/support_annotations_21_0_3.xml b/.idea/libraries/support_annotations_21_0_3.xml deleted file mode 100644 index c88ae64..0000000 --- a/.idea/libraries/support_annotations_21_0_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ 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 deleted file mode 100644 index 1f5aeb0..0000000 --- a/.idea/libraries/support_v4_21_0_3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 4f96d27..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - Android API 19 Platform - - - - - - - - - diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 51d776b..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 276779e..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 62fdcf6..fad2ec9 100755 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,12 +1,18 @@ CHANGELOG ENIGMANDROID +v0.1.5-not.yet.released< +*added missing licenses to class files +*Added proper documentation +*Extended input interpretation (number spelling in different languages, any unknown special +character now becomes 'X' + + 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/app/.gitignore b/app/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/app/app-release.apk b/app/app-release.apk deleted file mode 100644 index fc7dba4..0000000 Binary files a/app/app-release.apk and /dev/null differ diff --git a/app/build.gradle b/app/build.gradle old mode 100644 new mode 100755 index b82c414..467b24a --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 - buildToolsVersion "20.0.0" + compileSdkVersion 22 + buildToolsVersion "22.0.1" defaultConfig { applicationId "de.vanitasvitae.enigmandroid" minSdkVersion 15 - targetSdkVersion 21 - versionCode 9 - versionName "0.1.3-14.03.2015-beta" + targetSdkVersion 22 + versionCode 10 + versionName "0.1.4-15.08.2015-beta" } buildTypes { release { @@ -19,5 +19,5 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:21.+' + compile 'com.android.support:support-v4:22.2.1' } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro old mode 100644 new mode 100755 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml old mode 100644 new mode 100755 index 28ecdea..568284b --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,11 @@ + + + + + = 65 && x <= 90) //If x in [A..Z] - { - output = output + x; //Append to String - } - //if x is special symbol - else - { - if (x == '.' || x == ',' || x == '!' || x == '?' || x == ':') - { - //replace x with X and encrypt - output = output + 'X'; - } - } - } - return output; + return (26+input)%26; } /** @@ -198,6 +181,10 @@ public class Enigma } } + /** + * Set the plugboard + * @param p Plugboard + */ public void setPlugboard(Plugboard p) { this.plugboard = p; @@ -226,6 +213,28 @@ public class Enigma return configuration; } + /** + * Set the inputPreparator + * @param preparator concrete InputPreparator + */ + public void setInputPreparator(InputPreparator preparator) + { + this.inputPreparator = preparator; + } + + /** + * Return the inputPreparator + * @return inputPreparator + */ + public InputPreparator getInputPreparator() + { + return this.inputPreparator; + } + + /** + * set prefAnomaly variable + * @param b boolean + */ public void setPrefAnomaly(boolean b) { this.prefAnomaly = b; diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/InputPreparator.java b/app/src/main/java/de/vanitasvitae/enigmandroid/InputPreparator.java new file mode 100644 index 0000000..81eb0f8 --- /dev/null +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/InputPreparator.java @@ -0,0 +1,123 @@ +package de.vanitasvitae.enigmandroid; + +import java.text.Normalizer; + +/** + * Preparator class that prepares input text to only consist of [A..Z] + * 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 + */ +public abstract class InputPreparator +{ + /** + * Prepare the input String in a way that it only contains letters from [A..Z]. + * Replace special characters and spell numbers. + * @param input String + * @return prepared String + */ + public String prepareString(String input) + { + input = input.toUpperCase(); + input = input.replace("Ä","AE").replace("Ö","OE").replace("Ü","UE").replace("ß","SS"); + String output = ""; + + for (char x : input.toCharArray()) + { + if (x >= 65 && x <= 90) //x in [A..Z] + { + output = output + x; + } + else if (x >= 48 && x <= 57) //x in [0..9] + { + output = output + replaceNumber(x); + } + //x is special symbol + else + { + output = output + 'X'; + } + } + return output; + } + + /** + * Abstract method that spells numbers in a certain language specified by the implementation + * @param input character + * @return spelled number + */ + public abstract String replaceNumber(char input); + + /** + * Factory method that creates a specific InputPreparator + * @param language language alias that specifies the language (de,en) + * @return concrete InputPreparator + */ + public static InputPreparator createInputPreparator(String language) + { + switch (language) + { + case "de": return new InputPreparatorGerman(); + default: return new InputPreparatorEnglish(); + } + } +} + +/** + * Concrete implementation of a german InputPreparator + */ +class InputPreparatorGerman extends InputPreparator +{ + @Override + public String replaceNumber(char input) { + switch (input) + { + case '0': return "NULL"; + case '1': return "EINS"; + case '2': return "ZWEI"; + case '3': return "DREI"; + case '4': return "VIER"; + case '5': return "FUENF"; + case '6': return "SECHS"; + case '7': return "SIEBEN"; + case '8': return "ACHT"; + default: return "NEUN"; + } + } +} + +/** + * Concrete implementation of an english InputPreparator + */ +class InputPreparatorEnglish extends InputPreparator +{ + @Override + public String replaceNumber(char input) + { + switch (input) { + case '0': return "ZERO"; + case '1': return "ONE"; + case '2': return "TWO"; + case '3': return "THREE"; + case '4': return "FOUR"; + case '5': return "FIVE"; + case '6': return "SIX"; + case '7': return "SEVEN"; + case '8': return "EIGHT"; + default: return "NINE"; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java b/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java index 407ab4e..4f1525b 100755 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java @@ -1,21 +1,3 @@ -/** - * 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. - */ - package de.vanitasvitae.enigmandroid; import android.app.Activity; @@ -33,21 +15,38 @@ import android.widget.EditText; import android.widget.Spinner; import android.widget.ArrayAdapter; import android.widget.Toast; +/** + * Main Android Activity of the app + * 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 + */ public class MainActivity extends Activity { - private Menu menu; - private Spinner rotor1; - private Spinner rotor2; - private Spinner rotor3; - private Spinner reflector; - private Spinner rotor1Position; - private Spinner rotor2Position; - private Spinner rotor3Position; + private Spinner rotor1View; + private Spinner rotor2View; + private Spinner rotor3View; + private Spinner reflectorView; + private Spinner rotor1PositionView; + private Spinner rotor2PositionView; + private Spinner rotor3PositionView; - private EditText plugboard; - private EditText input; - private EditText output; + private EditText plugboardView; + private EditText inputView; + private EditText outputView; private static final int RESULT_SETTINGS = 1; private static final String URI_CHANGELOG = "https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt"; @@ -56,6 +55,7 @@ public class MainActivity extends Activity //memory for the ringSettings private int[] ringSettings = {0,0,0}; private boolean prefAnomaly; + private String prefNumericLanguage; @Override public void onCreate(Bundle savedInstanceState) @@ -63,7 +63,10 @@ public class MainActivity extends Activity super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_main); this.initLayout(); - this.prefAnomaly = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("prefAnomaly", true); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + this.prefAnomaly = sharedPreferences.getBoolean("prefAnomaly", true); + this.prefNumericLanguage = sharedPreferences.getString("prefNumericLanguage",getResources(). + getStringArray(R.array.pref_alias_numeric_spelling_language)[0]); this.resetLayout(); ActivitySingleton singleton = ActivitySingleton.getInstance(); singleton.setActivity(this); @@ -79,7 +82,7 @@ public class MainActivity extends Activity String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); if (sharedText != null) { - input.setText(sharedText); + inputView.setText(sharedText); } } } @@ -88,7 +91,6 @@ public class MainActivity extends Activity @Override public boolean onCreateOptionsMenu(Menu menu) { - this.menu = menu; this.getMenuInflater().inflate(R.menu.main, menu); return true; } @@ -109,7 +111,7 @@ public class MainActivity extends Activity } else if (id == R.id.action_choose_ringstellung) { - showRingsettingsDialog(); + showRingSettingsDialog(); return true; } else if (id == R.id.action_settings) @@ -124,15 +126,15 @@ public class MainActivity extends Activity } else if (id == R.id.action_send) { - if(output.getText().length() == 0) + if(outputView.getText().length() == 0) { - Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_LONG).show(); + Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show(); } else { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, output.getText().toString()); + sendIntent.putExtra(Intent.EXTRA_TEXT, outputView.getText().toString()); sendIntent.setType("text/plain"); startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to))); } @@ -148,25 +150,26 @@ public class MainActivity extends Activity public void updateEnigma(View v) { int[] conf = new int[10]; - conf[0] = rotor1.getSelectedItemPosition() + 1; - conf[1] = rotor2.getSelectedItemPosition() + 1; - conf[2] = rotor3.getSelectedItemPosition() + 1; - conf[3] = reflector.getSelectedItemPosition() + 1; - conf[4] = rotor1Position.getSelectedItemPosition() + 1; - conf[5] = rotor2Position.getSelectedItemPosition() + 1; - conf[6] = rotor3Position.getSelectedItemPosition() + 1; + conf[0] = rotor1View.getSelectedItemPosition() + 1; + conf[1] = rotor2View.getSelectedItemPosition() + 1; + conf[2] = rotor3View.getSelectedItemPosition() + 1; + conf[3] = reflectorView.getSelectedItemPosition() + 1; + conf[4] = rotor1PositionView.getSelectedItemPosition() + 1; + conf[5] = rotor2PositionView.getSelectedItemPosition() + 1; + conf[6] = rotor3PositionView.getSelectedItemPosition() + 1; conf[7] = ringSettings[0]; conf[8] = ringSettings[1]; conf[9] = ringSettings[2]; enigma = new Enigma(); - int[][] plugboardConfiguration = null; - plugboard.setText(plugboard.getText().toString().toUpperCase()); - plugboardConfiguration = Plugboard.parseConfigurationString(plugboard.getText().toString()); + int[][] plugboardConfiguration; + plugboardView.setText(plugboardView.getText().toString().toUpperCase()); + plugboardConfiguration = Plugboard.parseConfigurationString(plugboardView.getText().toString()); enigma.setConfiguration(conf); enigma.setPlugboard(new Plugboard(plugboardConfiguration)); enigma.setPrefAnomaly(prefAnomaly); + enigma.setInputPreparator(InputPreparator.createInputPreparator(prefNumericLanguage)); } /** @@ -177,12 +180,12 @@ public class MainActivity extends Activity */ public void doCrypto(View v) { - if(input.getText().length()!=0) { + if(inputView.getText().length()!=0) { updateEnigma(null); - String m = input.getText().toString(); - m = Enigma.prepare(m); - input.setText(m); - output.setText(enigma.encrypt(m)); + String m = inputView.getText().toString(); + m = enigma.getInputPreparator().prepareString(m); + inputView.setText(m); + outputView.setText(enigma.encrypt(m)); updateSpinner(enigma.getConfiguration()); } } @@ -193,17 +196,17 @@ public class MainActivity extends Activity */ private void resetLayout() { - rotor1.setSelection(0); - rotor2.setSelection(1); - rotor3.setSelection(2); - reflector.setSelection(1); - rotor1Position.setSelection(0); - rotor2Position.setSelection(0); - rotor3Position.setSelection(0); + rotor1View.setSelection(0); + rotor2View.setSelection(1); + rotor3View.setSelection(2); + reflectorView.setSelection(1); + rotor1PositionView.setSelection(0); + rotor2PositionView.setSelection(0); + rotor3PositionView.setSelection(0); ringSettings = new int[]{0,0,0}; - plugboard.setText(""); - input.setText(""); - output.setText(""); + plugboardView.setText(""); + inputView.setText(""); + outputView.setText(""); } /** @@ -214,63 +217,62 @@ public class MainActivity extends Activity Character[] charArray = new Character[26]; for(int i=0; i<26; i++) {charArray[i] = (char) (65+i);} - rotor1 = (Spinner) findViewById(R.id.rotor1); + rotor1View = (Spinner) findViewById(R.id.rotor1); ArrayAdapter rotor1Adapter = ArrayAdapter.createFromResource(this, R.array.enigma_rotors, android.R.layout.simple_spinner_item); rotor1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - rotor1.setAdapter(rotor1Adapter); + rotor1View.setAdapter(rotor1Adapter); - rotor2 = (Spinner) findViewById(R.id.rotor2); + rotor2View = (Spinner) findViewById(R.id.rotor2); ArrayAdapter rotor2Adapter = ArrayAdapter.createFromResource(this, R.array.enigma_rotors, android.R.layout.simple_spinner_item); rotor2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - rotor2.setAdapter(rotor2Adapter); + rotor2View.setAdapter(rotor2Adapter); - rotor3 = (Spinner) findViewById(R.id.rotor3); + rotor3View = (Spinner) findViewById(R.id.rotor3); ArrayAdapter rotor3Adapter = ArrayAdapter.createFromResource(this, R.array.enigma_rotors, android.R.layout.simple_spinner_item); rotor3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - rotor3.setAdapter(rotor3Adapter); + rotor3View.setAdapter(rotor3Adapter); - reflector = (Spinner) findViewById(R.id.reflector); + reflectorView = (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); - reflector.setAdapter(relfectorAdapter); + reflectorView.setAdapter(relfectorAdapter); - rotor1Position = (Spinner) findViewById(R.id.rotor1position); + rotor1PositionView = (Spinner) findViewById(R.id.rotor1position); 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); + rotor1PositionView.setAdapter(rotor1PositionAdapter); - rotor2Position = (Spinner) findViewById(R.id.rotor2position); + rotor2PositionView = (Spinner) findViewById(R.id.rotor2position); 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); + rotor2PositionView.setAdapter(rotor2PositionAdapter); - rotor3Position = (Spinner) findViewById(R.id.rotor3position); + rotor3PositionView = (Spinner) findViewById(R.id.rotor3position); 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); + rotor3PositionView.setAdapter(rotor3PositionAdapter); - plugboard = (EditText) findViewById(R.id.plugboard); - plugboard.setOnFocusChangeListener(new View.OnFocusChangeListener() { + plugboardView = (EditText) findViewById(R.id.plugboard); + plugboardView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { - if(!hasFocus) - { - plugboard.setText(plugboard.getText().toString().toUpperCase()); + if (!hasFocus) { + plugboardView.setText(plugboardView.getText().toString().toUpperCase()); } } }); - input = (EditText) findViewById(R.id.input); - output = (EditText) findViewById(R.id.output); + inputView = (EditText) findViewById(R.id.input); + outputView = (EditText) findViewById(R.id.output); - input.requestFocus(); + inputView.requestFocus(); } /** @@ -279,40 +281,40 @@ public class MainActivity extends Activity */ public void updateSpinner(int[] c) { - rotor1.setSelection(c[0] - 1); - rotor2.setSelection(c[1] - 1); - rotor3.setSelection(c[2] - 1); - rotor1Position.setSelection(c[4]); - rotor2Position.setSelection(c[5]); - rotor3Position.setSelection(c[6]); + rotor1View.setSelection(c[0] - 1); + rotor2View.setSelection(c[1] - 1); + rotor3View.setSelection(c[2] - 1); + rotor1PositionView.setSelection(c[4]); + rotor2PositionView.setSelection(c[5]); + rotor3PositionView.setSelection(c[6]); } /** * Show the dialog where the user can pick the ringsettings and set them if the user doesn't * abort. */ - public void showRingsettingsDialog() + public void showRingSettingsDialog() { - View ringsettingsView = View.inflate(this, R.layout.dialog_ringsettings, null); + 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); + final Spinner ring1 = (Spinner) ringSettingsView.findViewById(R.id.rotor1ring); 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]); - final Spinner ring2 = (Spinner) ringsettingsView.findViewById(R.id.rotor2ring); + final Spinner ring2 = (Spinner) ringSettingsView.findViewById(R.id.rotor2ring); 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]); - final Spinner ring3 = (Spinner) ringsettingsView.findViewById(R.id.rotor3ring); + final Spinner ring3 = (Spinner) ringSettingsView.findViewById(R.id.rotor3ring); ArrayAdapter ring3Adapter = new ArrayAdapter<>(this.getApplicationContext(), android.R.layout.simple_spinner_item,ringArray); ring3Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); @@ -321,7 +323,7 @@ public class MainActivity extends Activity AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.title_ringsetting); - builder.setView(ringsettingsView) + builder.setView(ringSettingsView) .setCancelable(true) .setPositiveButton(R.string.dialog_positiv, new DialogInterface.OnClickListener() { @@ -379,8 +381,12 @@ public class MainActivity extends Activity { SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); this.prefAnomaly = sharedPrefs.getBoolean("prefAnomaly", true); + this.prefNumericLanguage = sharedPrefs.getString("prefNumericLanguage",getResources(). + getStringArray(R.array.pref_alias_numeric_spelling_language)[0]); + ; break; } + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java b/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java index 3938d84..f182320 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/Plugboard.java @@ -6,7 +6,23 @@ import android.widget.Toast; import java.util.ArrayList; /** - * Created by vanitas on 12.08.15. + * Plugboard of the enigma + * 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 */ public class Plugboard { @@ -30,7 +46,7 @@ public class Plugboard /** * Configure the plugboard according to the given array. * - * @param configuration + * @param configuration two dimensional array of plugs */ public void setConfiguration(int[][] configuration) { @@ -68,7 +84,7 @@ public class Plugboard } else { input = input.toUpperCase(); - ArrayList plugList = new ArrayList(); + ArrayList plugList = new ArrayList<>(); int[] plug = new int[2]; for (int i = 0; i < input.length(); i++) { int c = input.charAt(i) - 65; diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Reflector.java b/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Reflector.java index fffe4e0..9917095 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Reflector.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Reflector.java @@ -1,7 +1,25 @@ package de.vanitasvitae.enigmandroid.rotors; /** - * Created by vanitas on 11.08.15. + * Reflector of the enigma machine. + * The reflector was used to reflect the scrambled signal at the end of the wiring back to + * go through another (reversed but not inverting) process of scrambling. + * 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 */ public class Reflector { @@ -9,6 +27,14 @@ public class Reflector protected int type; protected Integer[] connections; + /** + * This constructor is not accessible from outside this class file. + * Use the one of the createReflector* methods instead to create concrete Reflectors from + * outside this class file + * @param name phonetic name of the reflector (usually A,B,C) + * @param type type indicator of the reflector (A->1,...,C->3) + * @param connections wiring of the reflector as Integer array + */ protected Reflector(String name, int type, Integer[] connections) { this.name = name; @@ -16,21 +42,41 @@ public class Reflector this.connections = connections; } + /** + * Creates a reflector of type A + * @return ReflectorA + */ public static Reflector createReflectorA() { return new ReflectorA(); } + /** + * Creates a reflector of type B + * @return ReflectorB + */ public static Reflector createReflectorB() { return new ReflectorB(); } + /** + * Creates a reflector of type C + * @return ReflectorC + */ public static Reflector createReflectorC() { return new ReflectorC(); } + /** + * Factory method to create reflectors. + * @param type type of the created reflector + * 1 -> ReflectorA + * 2 -> ReflectorB + * anything else -> ReflectorC + * @return ReflectorA | ReflectorB | ReflectorC + */ public static Reflector createReflector(int type) { switch (type) @@ -41,31 +87,61 @@ public class Reflector } } + /** + * Substitute an input signal via the wiring of the reflector with a different (!) output. + * The output MUST not be equal to the input for any input, since this was not possible + * due to the electronic implementation of the historical enigma machine. + * @param input input signal + * @return encrypted (substituted) output + */ public int encrypt(int input) { return this.connections[normalize(input)]; } + /** + * Return the type indicator of the reflector + * @return type + */ public int getType() { return this.type; } + /** + * Return phonetic name of the reflector + * @return name + */ public String getName() { return this.name; } + /** + * Return the size (ie the number of wires/length of the connections array) of the reflector + * @return size + */ private int getRotorSize() { return this.connections.length; } + /** + * Normalize the input. + * Normalizing means keeping the input via modulo in the range from 0 to n-1, where n is equal + * to the size of the reflector. This is necessary since java allows negative modulo values, + * which can break this implementation + * @param input input signal + * @return "normalized" input signal + */ private int normalize(int input) { return (input + this.getRotorSize()) % this.getRotorSize(); } + /** + * Concrete implementation of ReflectorA + */ private static class ReflectorA extends Reflector { public ReflectorA() @@ -74,6 +150,9 @@ public class Reflector } } + /** + * Concrete implementation of ReflectorB + */ private static class ReflectorB extends Reflector { public ReflectorB() @@ -82,6 +161,9 @@ public class Reflector } } + /** + * Concrete implementation of ReflectorC + */ private static class ReflectorC extends Reflector { public ReflectorC() diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Rotor.java b/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Rotor.java index 1beee48..105b766 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Rotor.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/rotors/Rotor.java @@ -1,7 +1,28 @@ package de.vanitasvitae.enigmandroid.rotors; /** - * Created by vanitas on 11.08.15. + * Rotor super class and inner concrete implementations + * The rotors were the key feature of the enigma used to scramble up input signals into + * encrypted signals difficult to predict. The rotors rotated to achieve a poly-alphabetic + * substitution which was hard to break. Each signal passes the rotor twice. Once in "forward"- + * direction and once in "backwards"-direction. There was a set of 3 out of 5 rotors inside the + * enigma machine M4. + * 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 */ public class Rotor { @@ -14,6 +35,22 @@ public class Rotor protected int ringSetting; protected int rotation; + /** + * This constructor is not accessible from outside this class file. + * Use one of the createRotor* factory methods instead to create concrete Rotors. + * Note that connections and reversedConnections MUST be of the same size and that + * neither connections nor reversedConnections respectively MUST have any number between + * 0 and connections.length-1 only once (ie they represent permutations) + * @param name phonetic name of the rotor (usually I,II,...V) + * @param type type indicator (I -> 1,...,V -> 5) + * @param connections wiring of the rotor as Integer array + * @param reversedConnections inverse wiring used to encrypt in the opposite direction + * (connections[reversedConnections[i]] = i + * for all i in 0..getRotorSize()-1. + * @param turnOverNotch Position of the turnover notch + * @param ringSetting setting of the ring that holds the letters + * @param rotation rotation of the rotor + */ protected Rotor(String name, int type, Integer[] connections, Integer[] reversedConnections, int turnOverNotch, int ringSetting, int rotation) { @@ -26,6 +63,14 @@ public class Rotor this.rotation = rotation; } + /** + * Factory method that creates a rotor accordingly to the type. + * Also initialize the rotor with ringSetting and rotation. + * @param type type indicator (1..5) + * @param ringSetting setting of the outer ring (0..25) + * @param rotation rotation of the rotor + * @return Concrete rotor + */ public static Rotor createRotor(int type, int ringSetting, int rotation) { switch (type) @@ -38,53 +83,103 @@ public class Rotor } } + /** + * Create concrete Rotor of type 1 (I) initialized with ringSetting and rotation + * @param ringSetting setting of the outer ring + * @param rotation rotation of the rotor + * @return RotorI + */ public static Rotor createRotorI(int ringSetting, int rotation) { return new RotorI(ringSetting, rotation); } + /** + * Create concrete Rotor of type 2 (II) initialized with ringSetting and rotation + * @param ringSetting setting of the outer ring + * @param rotation rotation of the rotor + * @return RotorI + */ public static Rotor createRotorII(int ringSetting, int rotation) { return new RotorII(ringSetting, rotation); } + /** + * Create concrete Rotor of type 3 (III) initialized with ringSetting and rotation + * @param ringSetting setting of the outer ring + * @param rotation rotation of the rotor + * @return RotorI + */ public static Rotor createRotorIII(int ringSetting, int rotation) { return new RotorIII(ringSetting, rotation); } + /** + * Create concrete Rotor of type 4 (IV) initialized with ringSetting and rotation + * @param ringSetting setting of the outer ring + * @param rotation rotation of the rotor + * @return RotorI + */ public static Rotor createRotorIV(int ringSetting, int rotation) { return new RotorIV(ringSetting, rotation); } + /** + * Create concrete Rotor of type 5 (V) initialized with ringSetting and rotation + * @param ringSetting setting of the outer ring + * @param rotation rotation of the rotor + * @return RotorI + */ public static Rotor createRotorV(int ringSetting, int rotation) { return new RotorV(ringSetting, rotation); } + /** + * Encrypt an input signal via the internal wiring in "forward" direction (using connections) + * @param input signal + * @return encrypted signal + */ public int encryptForward(int input) { return this.connections[normalize(input)]; } + /** + * Encrypt an input signal via the internal wiring in "backwards" direction (using + * reversedConnections) + * @param input signal + * @return encrypted signal + */ public int encryptBackward(int input) { return this.reversedConnections[normalize(input)]; } + /** + * Return the type indicator (usually 1..5) + * @return type indicator + */ public int getType() { return this.type; } + /** + * Return the current rotation of the rotor. + * The rotation consists of the actual rotation - the ringSetting + * @return rotation-ringSetting + */ public int getRotation() { return this.rotation - this.getRingSetting(); } /** - * increment rotation of the rotor by one. + * Increment rotation of the rotor by one. */ public void rotate() { @@ -92,9 +187,8 @@ public class Rotor } /** - * Return true, if rotor is at a position, where it turns over the next rotor - * - * @return boolean + * Return true, if the rotor is at a position, where it turns over the next rotor by one + * @return rotation==turnOverNotch */ public boolean isAtTurnoverPosition() { @@ -102,31 +196,28 @@ public class Rotor } /** - * The Double Turn Anomaly (deutsch: Doppelsprung Anomalie) is an anomaly in the rotor movement + * Return true, if the rotor is in a position where the double turn anomaly happens. + * The double turn anomaly (german: Doppelsprung-Anomalie) is an anomaly in the rotor movement * caused by the mechanical implementation of the enigma. * Whenever the rightmost rotor turns the middle rotor AND the middle rotor is only one move * from turning the leftmost rotor, the middle rotor turns again with the next character. * So technically there are only 26*25*26 possible rotor settings for any but firmly 3 rotors. - * - * @return boolean + * @return rotation == turnOverNotch-1 */ public boolean doubleTurnAnomaly() { - return this.rotation == this.turnOverNotch - 1; + return this.rotation == this.getTurnOver() - 1; } - @SuppressWarnings("unused") /** * Returns the position of the turnover notch - * - * @return turnOver + * @return turnOverNotch */ public int getTurnOver() { return this.turnOverNotch; } - @SuppressWarnings("unused") /** * Return ringSettings of the rotor * @return ringSetting @@ -136,21 +227,41 @@ public class Rotor return this.ringSetting; } + /** + * Returns the phonetic name of the rotor + * @return name + */ public String getName() { return this.name; } + /** + * Returns the size (ie the number of wires/size of the connections array) + * of the rotor + * @return size + */ public int getRotorSize() { return this.connections.length; } + /** + * Normalize the input. + * Normalizing means keeping the input via modulo in the range from 0 to n-1, where n is equal + * to the size of the rotor. This is necessary since java allows negative modulo values, + * which can break this implementation + * @param input input signal + * @return "normalized" input signal + */ public int normalize(int input) { return (input + this.getRotorSize()) % this.getRotorSize(); } + /** + * Concrete implementation of Rotor of type 1 (I) + */ private static class RotorI extends Rotor { public RotorI(int ringSetting, int rotation) @@ -162,6 +273,9 @@ public class Rotor } } + /** + * Concrete implementation of Rotor of type 2 (II) + */ private static class RotorII extends Rotor { public RotorII(int ringSetting, int rotation) @@ -173,6 +287,9 @@ public class Rotor } } + /** + * Concrete implementation of Rotor of type 3 (III) + */ private static class RotorIII extends Rotor { public RotorIII(int ringSetting, int rotation) @@ -184,6 +301,9 @@ public class Rotor } } + /** + * Concrete implementation of Rotor of type 4 (IV) + */ private static class RotorIV extends Rotor { public RotorIV(int ringSetting, int rotation) @@ -195,6 +315,9 @@ public class Rotor } } + /** + * Concrete implementation of Rotor of type 5 (V) + */ private static class RotorV extends Rotor { public RotorV(int ringSetting, int rotation) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4d66f99..17167ff 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -144,6 +144,7 @@ android:layout_width="match_parent" android:layout_height="30pt" android:id="@+id/plugboard" + android:inputType="textNoSuggestions" android:hint="@string/hint_enigma_plugboard" android:layout_below="@+id/lin_lay_2"/> @@ -158,13 +159,14 @@ android:layout_weight=".50" android:layout_height="match_parent" android:id="@+id/input" + android:inputType="textNoSuggestions" android:hint="@string/hint_enigma_type_here" /> @@ -178,7 +180,6 @@