diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d774817..ee7399d 100755 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,8 +1,10 @@ CHANGELOG ENIGMANDROID v0.1.9-not-yet-released< +*Added option to share/receive configurations via QR-Code (ZXing Barcode Scanner) +*Prevent user from setting incomplete reflector wiring +*Add option to generate configuration from passphrase *TODO: Add Enigma Z (Probably wont happen due to lack of information :/) *TODO: Add multi-Enigma (select any rotor/reflector etc. Probably wont happen too soon) -*TODO: Enigma configuration from/to seed (text or qr code) v0.1.8-27.09.2015< *Added Enigma G31 diff --git a/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java b/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java new file mode 100644 index 0000000..d5628e8 --- /dev/null +++ b/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java @@ -0,0 +1,506 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.ActivityNotFoundException; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +/** + *

A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple + * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the + * project's source code.

+ * + *

Initiating a barcode scan

+ * + *

To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait + * for the result in your app.

+ * + *

It does require that the Barcode Scanner (or work-alike) application is installed. The + * {@link #initiateScan()} method will prompt the user to download the application, if needed.

+ * + *

There are a few steps to using this integration. First, your {@link Activity} must implement + * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:

+ * + *
{@code
+ * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ *   IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
+ *   if (scanResult != null) {
+ *     // handle scan result
+ *   }
+ *   // else continue with any other code you need in the method
+ *   ...
+ * }
+ * }
+ * + *

This is where you will handle a scan result.

+ * + *

Second, just call this in response to a user action somewhere to begin the scan process:

+ * + *
{@code
+ * IntentIntegrator integrator = new IntentIntegrator(yourActivity);
+ * integrator.initiateScan();
+ * }
+ * + *

Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the + * user was prompted to download the application. This lets the calling app potentially manage the dialog. + * In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()} + * method.

+ * + *

You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use + * {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and + * yes/no button labels can be changed.

+ * + *

Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used + * to invoke the scanner. This can be used to set additional options not directly exposed by this + * simplified API.

+ * + *

By default, this will only allow applications that are known to respond to this intent correctly + * do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}. + * For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.

+ * + *

Sharing text via barcode

+ * + *

To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.

+ * + *

Some code, particularly download integration, was contributed from the Anobiit application.

+ * + *

Enabling experimental barcode formats

+ * + *

Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as + * PDF417. Use {@link #initiateScan(java.util.Collection)} with + * a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such + * formats.

+ * + * @author Sean Owen + * @author Fred Lin + * @author Isaac Potoczny-Jones + * @author Brad Drehmer + * @author gcstang + */ +public class IntentIntegrator { + + public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits + private static final String TAG = IntentIntegrator.class.getSimpleName(); + + public static final String DEFAULT_TITLE = "Install Barcode Scanner?"; + public static final String DEFAULT_MESSAGE = + "This application requires Barcode Scanner. Would you like to install it?"; + public static final String DEFAULT_YES = "Yes"; + public static final String DEFAULT_NO = "No"; + + private static final String BS_PACKAGE = "com.google.zxing.client.android"; + private static final String BSPLUS_PACKAGE = "com.srowen.bs.android"; + + // supported barcode formats + public static final Collection PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14"); + public static final Collection ONE_D_CODE_TYPES = + list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128", + "ITF", "RSS_14", "RSS_EXPANDED"); + public static final Collection QR_CODE_TYPES = Collections.singleton("QR_CODE"); + public static final Collection DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX"); + + public static final Collection ALL_CODE_TYPES = null; + + public static final List TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE); + public static final List TARGET_ALL_KNOWN = list( + BSPLUS_PACKAGE, // Barcode Scanner+ + BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple + BS_PACKAGE // Barcode Scanner + // What else supports this intent? + ); + + private final Activity activity; + private final Fragment fragment; + + private String title; + private String message; + private String buttonYes; + private String buttonNo; + private List targetApplications; + private final Map moreExtras = new HashMap(3); + + /** + * @param activity {@link Activity} invoking the integration + */ + public IntentIntegrator(Activity activity) { + this.activity = activity; + this.fragment = null; + initializeConfiguration(); + } + + /** + * @param fragment {@link Fragment} invoking the integration. + * {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead + * of an {@link Activity} + */ + public IntentIntegrator(Fragment fragment) { + this.activity = fragment.getActivity(); + this.fragment = fragment; + initializeConfiguration(); + } + + private void initializeConfiguration() { + title = DEFAULT_TITLE; + message = DEFAULT_MESSAGE; + buttonYes = DEFAULT_YES; + buttonNo = DEFAULT_NO; + targetApplications = TARGET_ALL_KNOWN; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setTitleByID(int titleID) { + title = activity.getString(titleID); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setMessageByID(int messageID) { + message = activity.getString(messageID); + } + + public String getButtonYes() { + return buttonYes; + } + + public void setButtonYes(String buttonYes) { + this.buttonYes = buttonYes; + } + + public void setButtonYesByID(int buttonYesID) { + buttonYes = activity.getString(buttonYesID); + } + + public String getButtonNo() { + return buttonNo; + } + + public void setButtonNo(String buttonNo) { + this.buttonNo = buttonNo; + } + + public void setButtonNoByID(int buttonNoID) { + buttonNo = activity.getString(buttonNoID); + } + + public Collection getTargetApplications() { + return targetApplications; + } + + public final void setTargetApplications(List targetApplications) { + if (targetApplications.isEmpty()) { + throw new IllegalArgumentException("No target applications"); + } + this.targetApplications = targetApplications; + } + + public void setSingleTargetApplication(String targetApplication) { + this.targetApplications = Collections.singletonList(targetApplication); + } + + public Map getMoreExtras() { + return moreExtras; + } + + public final void addExtra(String key, Object value) { + moreExtras.put(key, value); + } + + /** + * Initiates a scan for all known barcode types with the default camera. + * + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan() { + return initiateScan(ALL_CODE_TYPES, -1); + } + + /** + * Initiates a scan for all known barcode types with the specified camera. + * + * @param cameraId camera ID of the camera to use. A negative value means "no preference". + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan(int cameraId) { + return initiateScan(ALL_CODE_TYPES, cameraId); + } + + /** + * Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan(Collection desiredBarcodeFormats) { + return initiateScan(desiredBarcodeFormats, -1); + } + + /** + * Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for + * @param cameraId camera ID of the camera to use. A negative value means "no preference". + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog initiateScan(Collection desiredBarcodeFormats, int cameraId) { + Intent intentScan = new Intent(BS_PACKAGE + ".SCAN"); + intentScan.addCategory(Intent.CATEGORY_DEFAULT); + + // check which types of codes to scan for + if (desiredBarcodeFormats != null) { + // set the desired barcode types + StringBuilder joinedByComma = new StringBuilder(); + for (String format : desiredBarcodeFormats) { + if (joinedByComma.length() > 0) { + joinedByComma.append(','); + } + joinedByComma.append(format); + } + intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString()); + } + + // check requested camera ID + if (cameraId >= 0) { + intentScan.putExtra("SCAN_CAMERA_ID", cameraId); + } + + String targetAppPackage = findTargetAppPackage(intentScan); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intentScan.setPackage(targetAppPackage); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + attachMoreExtras(intentScan); + startActivityForResult(intentScan, REQUEST_CODE); + return null; + } + + /** + * Start an activity. This method is defined to allow different methods of activity starting for + * newer versions of Android and for compatibility library. + * + * @param intent Intent to start. + * @param code Request code for the activity + * @see android.app.Activity#startActivityForResult(Intent, int) + * @see android.app.Fragment#startActivityForResult(Intent, int) + */ + protected void startActivityForResult(Intent intent, int code) { + if (fragment == null) { + activity.startActivityForResult(intent, code); + } else { + fragment.startActivityForResult(intent, code); + } + } + + private String findTargetAppPackage(Intent intent) { + PackageManager pm = activity.getPackageManager(); + List availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (availableApps != null) { + for (String targetApp : targetApplications) { + if (contains(availableApps, targetApp)) { + return targetApp; + } + } + } + return null; + } + + private static boolean contains(Iterable availableApps, String targetApp) { + for (ResolveInfo availableApp : availableApps) { + String packageName = availableApp.activityInfo.packageName; + if (targetApp.equals(packageName)) { + return true; + } + } + return false; + } + + private AlertDialog showDownloadDialog() { + AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); + downloadDialog.setTitle(title); + downloadDialog.setMessage(message); + downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + String packageName; + if (targetApplications.contains(BS_PACKAGE)) { + // Prefer to suggest download of BS if it's anywhere in the list + packageName = BS_PACKAGE; + } else { + // Otherwise, first option: + packageName = targetApplications.get(0); + } + Uri uri = Uri.parse("market://details?id=" + packageName); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + try { + if (fragment == null) { + activity.startActivity(intent); + } else { + fragment.startActivity(intent); + } + } catch (ActivityNotFoundException anfe) { + // Hmm, market is not installed + Log.w(TAG, "Google Play is not installed; cannot install " + packageName); + } + } + }); + downloadDialog.setNegativeButton(buttonNo, null); + downloadDialog.setCancelable(true); + return downloadDialog.show(); + } + + + /** + *

Call this from your {@link Activity}'s + * {@link Activity#onActivityResult(int, int, Intent)} method.

+ * + * @param requestCode request code from {@code onActivityResult()} + * @param resultCode result code from {@code onActivityResult()} + * @param intent {@link Intent} from {@code onActivityResult()} + * @return null if the event handled here was not related to this class, or + * else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning, + * the fields will be null. + */ + public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK) { + String contents = intent.getStringExtra("SCAN_RESULT"); + String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT"); + byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES"); + int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE); + Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation; + String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL"); + return new IntentResult(contents, + formatName, + rawBytes, + orientation, + errorCorrectionLevel); + } + return new IntentResult(); + } + return null; + } + + + /** + * Defaults to type "TEXT_TYPE". + * + * @param text the text string to encode as a barcode + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + * @see #shareText(CharSequence, CharSequence) + */ + public final AlertDialog shareText(CharSequence text) { + return shareText(text, "TEXT_TYPE"); + } + + /** + * Shares the given text by encoding it as a barcode, such that another user can + * scan the text off the screen of the device. + * + * @param text the text string to encode as a barcode + * @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants. + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog shareText(CharSequence text, CharSequence type) { + Intent intent = new Intent(); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setAction(BS_PACKAGE + ".ENCODE"); + intent.putExtra("ENCODE_TYPE", type); + intent.putExtra("ENCODE_DATA", text); + String targetAppPackage = findTargetAppPackage(intent); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intent.setPackage(targetAppPackage); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + attachMoreExtras(intent); + if (fragment == null) { + activity.startActivity(intent); + } else { + fragment.startActivity(intent); + } + return null; + } + + private static List list(String... values) { + return Collections.unmodifiableList(Arrays.asList(values)); + } + + private void attachMoreExtras(Intent intent) { + for (Map.Entry entry : moreExtras.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + // Kind of hacky + if (value instanceof Integer) { + intent.putExtra(key, (Integer) value); + } else if (value instanceof Long) { + intent.putExtra(key, (Long) value); + } else if (value instanceof Boolean) { + intent.putExtra(key, (Boolean) value); + } else if (value instanceof Double) { + intent.putExtra(key, (Double) value); + } else if (value instanceof Float) { + intent.putExtra(key, (Float) value); + } else if (value instanceof Bundle) { + intent.putExtra(key, (Bundle) value); + } else { + intent.putExtra(key, value.toString()); + } + } + } + +} diff --git a/app/src/main/java/com/google/zxing/integration/android/IntentResult.java b/app/src/main/java/com/google/zxing/integration/android/IntentResult.java new file mode 100644 index 0000000..2469af9 --- /dev/null +++ b/app/src/main/java/com/google/zxing/integration/android/IntentResult.java @@ -0,0 +1,95 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +/** + *

Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.

+ * + * @author Sean Owen + */ +public final class IntentResult { + + private final String contents; + private final String formatName; + private final byte[] rawBytes; + private final Integer orientation; + private final String errorCorrectionLevel; + + IntentResult() { + this(null, null, null, null, null); + } + + IntentResult(String contents, + String formatName, + byte[] rawBytes, + Integer orientation, + String errorCorrectionLevel) { + this.contents = contents; + this.formatName = formatName; + this.rawBytes = rawBytes; + this.orientation = orientation; + this.errorCorrectionLevel = errorCorrectionLevel; + } + + /** + * @return raw content of barcode + */ + public String getContents() { + return contents; + } + + /** + * @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names. + */ + public String getFormatName() { + return formatName; + } + + /** + * @return raw bytes of the barcode content, if applicable, or null otherwise + */ + public byte[] getRawBytes() { + return rawBytes; + } + + /** + * @return rotation of the image, in degrees, which resulted in a successful scan. May be null. + */ + public Integer getOrientation() { + return orientation; + } + + /** + * @return name of the error correction level used in the barcode, if applicable + */ + public String getErrorCorrectionLevel() { + return errorCorrectionLevel; + } + + @Override + public String toString() { + StringBuilder dialogText = new StringBuilder(100); + dialogText.append("Format: ").append(formatName).append('\n'); + dialogText.append("Contents: ").append(contents).append('\n'); + int rawBytesLength = rawBytes == null ? 0 : rawBytes.length; + dialogText.append("Raw bytes: (").append(rawBytesLength).append(" bytes)\n"); + dialogText.append("Orientation: ").append(orientation).append('\n'); + dialogText.append("EC level: ").append(errorCorrectionLevel).append('\n'); + return dialogText.toString(); + } + +} diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java b/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java index 91b7454..98db67f 100755 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/MainActivity.java @@ -15,10 +15,14 @@ import android.view.MenuItem; import android.view.View; import android.widget.Toast; -import java.util.ArrayList; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; +import de.vanitasvitae.enigmandroid.enigma.Enigma; +import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle; import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer; import de.vanitasvitae.enigmandroid.layout.LayoutContainer; +import de.vanitasvitae.enigmandroid.layout.PassphraseDialogBuilder; /** * Main Android Activity of the app @@ -44,6 +48,7 @@ public class MainActivity extends Activity private static final int RESULT_SETTINGS = 1; private static final String URI_CHANGELOG = "https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt"; + public static final String APP_ID = "EnigmAndroid"; LayoutContainer layoutContainer; protected String prefMachineType; @@ -55,7 +60,6 @@ public class MainActivity extends Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Log.d("Activity","OnCreate!"); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); this.prefMachineType = sharedPreferences.getString(SettingsActivity.PREF_MACHINE_TYPE, getResources(). getStringArray(R.array.pref_alias_machine_type)[0]); @@ -81,65 +85,6 @@ public class MainActivity extends Activity } } - /** - * Unfortunately we have to overwrite this, because on orientation changes the LayoutContainer - * will reset and we would lose information about plugboard, reflector-wiring and ring settings. - * These info are we saving here. - * TODO: Find more elegant solution - * @param outState state - */ - @Override - protected void onSaveInstanceState (Bundle outState) - { - ArrayList plugboard = new ArrayList<>(); - if(layoutContainer.getState().getConfigurationPlugboard() != null) { - for (int i : layoutContainer.getState().getConfigurationPlugboard()) plugboard.add(i); - } - outState.putIntegerArrayList("plugboard",plugboard); - - ArrayList reflector = new ArrayList<>(); - if(layoutContainer.getState().getConfigurationReflector() != null) { - for (int i : layoutContainer.getState().getConfigurationReflector()) reflector.add(i); - } - outState.putIntegerArrayList("reflector", reflector); - - outState.putInt("ring1", layoutContainer.getState().getRingSettingRotor1()); - outState.putInt("ring2", layoutContainer.getState().getRingSettingRotor2()); - outState.putInt("ring3", layoutContainer.getState().getRingSettingRotor3()); - outState.putInt("ring4", layoutContainer.getState().getRingSettingRotor4()); - outState.putInt("ringR", layoutContainer.getState().getRingSettingReflector()); - - super.onSaveInstanceState(outState); - } - - /** - * Here we get back values previously saved int onSaveInstanceState - * @param savedInstanceState state - */ - @Override - protected void onRestoreInstanceState (Bundle savedInstanceState) - { - ArrayList plugboard = savedInstanceState.getIntegerArrayList("plugboard"); - if(plugboard != null && plugboard.size() != 0) { - int[] p = new int[plugboard.size()]; - for (int i = 0; i < plugboard.size(); i++) p[i] = plugboard.get(i); - layoutContainer.getState().setConfigurationPlugboard(p); - } - - ArrayList reflector = savedInstanceState.getIntegerArrayList("reflector"); - if(reflector != null && reflector.size() != 0) { - int[] r = new int[reflector.size()]; - for (int i = 0; i < reflector.size(); i++) r[i] = reflector.get(i); - layoutContainer.getState().setConfigurationReflector(r); - } - - layoutContainer.getState().setRingSettingRotor1(savedInstanceState.getInt("ring1")); - layoutContainer.getState().setRingSettingRotor2(savedInstanceState.getInt("ring2")); - layoutContainer.getState().setRingSettingRotor3(savedInstanceState.getInt("ring3")); - layoutContainer.getState().setRingSettingRotor4(savedInstanceState.getInt("ring4")); - layoutContainer.getState().setRingSettingReflector(savedInstanceState.getInt("ringR")); - } - @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -204,6 +149,8 @@ public class MainActivity extends Activity layoutContainer = LayoutContainer.createLayoutContainer(prefMachineType); layoutContainer.setInputPreparer(InputPreparer.createInputPreparer()); layoutContainer.getInput().setText(savedInput); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + sharedPreferences.edit().putString(SettingsActivity.PREF_MACHINE_TYPE, type); } } @@ -266,6 +213,11 @@ public class MainActivity extends Activity return prefMessageFormatting; } + public void onDialogFinished(EnigmaStateBundle state) + { + layoutContainer.getEnigma().setState(state); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -290,12 +242,12 @@ public class MainActivity extends Activity else if (id == R.id.action_random_configuration) { layoutContainer.getEnigma().randomState(); - layoutContainer.setLayoutState(layoutContainer.getEnigma().getState()); + layoutContainer.syncStateFromEnigmaToLayout(); Toast.makeText(getApplicationContext(), R.string.message_random, Toast.LENGTH_SHORT).show(); return true; } - else if (id == R.id.action_choose_ringstellung) + else if (id == R.id.action_choose_ringsetting) { layoutContainer.showRingSettingsDialog(); return true; @@ -325,6 +277,25 @@ public class MainActivity extends Activity startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to))); } } + else if (id == R.id.action_receive_scan) + { + IntentIntegrator integrator = new IntentIntegrator(this); + integrator.initiateScan(); + return true; + } + else if(id == R.id.action_share_scan) + { + IntentIntegrator QRIntegrator = new IntentIntegrator(this); + layoutContainer.syncStateFromLayoutToEnigma(); + Log.d(APP_ID, "Sharing configuration to QR: " + layoutContainer.getEnigma().stateToString()); + QRIntegrator.shareText(layoutContainer.getEnigma().stateToString()); + return true; + } + else if(id == R.id.action_enter_seed) + { + new PassphraseDialogBuilder().showDialog(); + return true; + } return super.onOptionsItemSelected(item); } @@ -390,10 +361,37 @@ public class MainActivity extends Activity getResources().getStringArray(R.array.pref_alias_message_formatting)[0])); break; } - + case IntentIntegrator.REQUEST_CODE: + IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); + if (scanResult != null) { + String content = scanResult.getContents(); + if(content == null) Log.e(APP_ID, "Error! Received nothing from QR-Code!"); + else Log.d(APP_ID, "Received "+content+" from QR-Code!"); + restoreStateFromCode(content); + } } } + private void restoreStateFromCode(String mem) + { + setPrefMachineType(Enigma.chooseEnigmaFromSave(mem)); + updateContentView(); + layoutContainer = LayoutContainer.createLayoutContainer(getPrefMachineType()); + layoutContainer.getEnigma().restoreState(mem); + layoutContainer.setInputPreparer(InputPreparer.createInputPreparer()); + layoutContainer.syncStateFromEnigmaToLayout(); + } + + public void createStateFromSeed(String seed) + { + setPrefMachineType(Enigma.chooseEnigmaFromSeed(seed)); + updateContentView(); + layoutContainer = LayoutContainer.createLayoutContainer(getPrefMachineType()); + layoutContainer.getEnigma().setStateFromSeed(seed); + layoutContainer.setInputPreparer(InputPreparer.createInputPreparer()); + layoutContainer.syncStateFromEnigmaToLayout(); + } + /** * Open the web page with the URL url * @param url URL of the website diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma.java index 0aaa148..82019ab 100755 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma.java @@ -1,5 +1,8 @@ package de.vanitasvitae.enigmandroid.enigma; +import java.security.SecureRandom; +import java.util.Random; + /** * Main component of the Enigma machine * This is the mostly abstract base of any enigma machine. @@ -23,14 +26,26 @@ package de.vanitasvitae.enigmandroid.enigma; public abstract class Enigma { protected static String machineType; + protected int machineTypeOffset = 0; protected boolean doAnomaly = false; //Has the time come to handle an anomaly? protected boolean prefAnomaly; //Do you WANT to simulate the anomaly? + protected Random rand; + public Enigma(int off) + { + this.machineTypeOffset = off; + initialize(); + } public Enigma() { initialize(); } + public int getMachineTypeOffset() + { + return machineTypeOffset; + } + /** * Set the enigma to an initial state */ @@ -66,11 +81,20 @@ public abstract class Enigma public abstract void nextState(); /** - * Set the enigma to a random state. + * Set the enigma into a completely random state using a unseeded SecureRandom object. + */ + public void randomState() + { + this.rand = new SecureRandom(); + generateState(); + } + + /** + * Set the enigma to a random state based on the initialization of rand. * Don not choose a rotor twice, set random rotations, ringSettings, ukw and possibly * plugboard / rewirable ukw configurations. */ - public abstract void randomState(); + protected abstract void generateState(); /** * Substitute char k by sending the signal through the enigma. @@ -94,6 +118,53 @@ public abstract class Enigma */ public abstract EnigmaStateBundle getState(); + /** + * Set the rand into a certain state based on seed. + * Then set the enigmas state. + * @param seed + */ + public void setStateFromSeed(String seed) + { + rand = new Random(seed.hashCode()); + generateState(); + } + + public abstract void restoreState(String mem); + + public abstract String stateToString(); + + public static String numToMachineType(int n) + { + switch (n) { + case 0: return "I"; + case 1: return "M3"; + case 2: return "M4"; + case 3: return "G31"; + case 4: return "G312"; + case 5: return "G260"; + case 6: return "D"; + case 7: return "K"; + case 8: return "KS"; + case 9: return "KSA"; + case 10: return "R"; + default: return "T"; + } + } + + public static String chooseEnigmaFromSeed(String seed) + { + return numToMachineType(seed.hashCode() % 12); + } + + public static String chooseEnigmaFromSave(String save) + { + int index = save.indexOf(":"); + if(index != -1) save = save.substring(0, index); + long s = Long.valueOf(save); + return numToMachineType(getValue(s,12)); + } + + /** * set prefAnomaly variable * @param b boolean @@ -112,4 +183,40 @@ public abstract class Enigma return machineType; } + /** + * + * @param s source + * @param d domain (max value) of the value + * @return value + */ + protected static int getValue(long s, int d) + { + return (int) ((s%d)+d)%d; + } + + /** + * remove a digit of domain d from source s + * @param s source + * @param d domain (max value) + * @return trimmed source + */ + protected static long removeDigit(long s, int d) + { + return (s-(s%d))/d; + } + + /** + * + * @param s source + * @param b base (max value) + * @param v actual value + * @return lengthened source + */ + protected static long addDigit(long s, int v, int b) + { + long x = s; + x*=b; + x+=(v%b); + return x; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_D.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_D.java index e1beb4f..e99e557 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_D.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_D.java @@ -1,8 +1,5 @@ package de.vanitasvitae.enigmandroid.enigma; -import java.security.SecureRandom; -import java.util.Random; - import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; @@ -34,6 +31,7 @@ public class Enigma_D extends Enigma { protected Reflector.ReflectorEnigma_D_KD_G31 reflector; + protected static int machineTypeOffset = 70; public Enigma_D() { super(); @@ -44,10 +42,10 @@ public class Enigma_D extends Enigma { public void initialize() { this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(70, 0, 0); - this.rotor2 = Rotor.createRotor(71, 0, 0); - this.rotor3 = Rotor.createRotor(72, 0, 0); - this.reflector = (Reflector.ReflectorEnigma_D_KD_G31) Reflector.createReflector(70); + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.reflector = (Reflector.ReflectorEnigma_D_KD_G31) Reflector.createReflector(machineTypeOffset); } @Override @@ -66,9 +64,7 @@ public class Enigma_D extends Enigma { } @Override - public void randomState() - { - Random rand = new SecureRandom(); + protected void generateState() { int rot1 = rand.nextInt(26); int rot2 = rand.nextInt(26); int rot3 = rand.nextInt(26); @@ -78,12 +74,14 @@ public class Enigma_D extends Enigma { int ring3 = rand.nextInt(26); int ringRef = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(70, rot1, ring1); - this.rotor2 = Rotor.createRotor(71, rot2, ring2); - this.rotor3 = Rotor.createRotor(72, rot3, ring3); - this.reflector = (Reflector.ReflectorEnigma_D_KD_G31) Reflector.createReflector(70); + this.rotor1 = Rotor.createRotor(machineTypeOffset, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, rot3, ring3); + + this.reflector = (Reflector.ReflectorEnigma_D_KD_G31) Reflector.createReflector(machineTypeOffset); this.reflector.setRotation(rotRef); this.reflector.setRingSetting(ringRef); + this.reflector.setConfiguration(Plugboard.seedToReflectorConfiguration(rand)); } @Override @@ -153,4 +151,54 @@ public class Enigma_D extends Enigma { return state; } + + @Override + public void restoreState(String mem) + { + String reflectorConf = mem.substring(mem.lastIndexOf(":r")+2); + long s = Long.valueOf(mem.substring(0, mem.indexOf(":r"))); + + s = removeDigit(s, 12); //Remove machine type + int rot1 = getValue(s, 26); + s = removeDigit(s, 26); + int ring1 = getValue(s, 26); + s = removeDigit(s, 26); + int rot2 = getValue(s, 26); + s = removeDigit(s, 26); + int ring2 = getValue(s, 26); + s = removeDigit(s, 26); + int rot3 = getValue(s, 26); + s = removeDigit(s, 26); + int ring3 = getValue(s, 26); + s = removeDigit(s, 26); + int rotRef = getValue(s, 26); + s = removeDigit(s, 26); + int ringRef = getValue(s, 26); + + this.rotor1 = Rotor.createRotor(machineTypeOffset, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, rot3, ring3); + this.reflector = (Reflector.ReflectorEnigma_D_KD_G31) Reflector.createReflector(machineTypeOffset); + this.reflector.setConfiguration(Plugboard.stringToConfiguration(reflectorConf)); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + } + + @Override + public String stateToString() { + String save = ""; + long s = reflector.getRingSetting(); + s = addDigit(s, reflector.getRotation(), 26); + s = addDigit(s, rotor3.getRingSetting(), 26); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); + s = addDigit(s, 6, 12); //Machine #6 + + save = save+s; + save = save + ":r" + Plugboard.configurationToString(getState().getConfigurationReflector()); + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G260.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G260.java index 4270eba..c686aab 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G260.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G260.java @@ -1,11 +1,5 @@ package de.vanitasvitae.enigmandroid.enigma; -import java.security.SecureRandom; -import java.util.Random; - -import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; -import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; - /** * Implementation of the Enigma machine of type G31 (Abwehr) * Copyright (C) 2015 Paul Schaub @@ -29,43 +23,31 @@ public class Enigma_G260 extends Enigma_G31 { public Enigma_G260() { - super(); + super(60); machineType = "G260"; } - @Override - public void initialize() - { - this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(60, 0, 0); - this.rotor2 = Rotor.createRotor(61, 0, 0); - this.rotor3 = Rotor.createRotor(62, 0, 0); - this.reflector = Reflector.createReflector(60); - } + @Override - public void randomState() + public String stateToString() { - Random rand = new SecureRandom(); + String save = ""; + long s = reflector.getRingSetting(); + s = addDigit(s, reflector.getRotation(), 26); + s = addDigit(s, rotor3.getRingSetting(), 26); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); - int rotor1, rotor2=-1, rotor3=-1; - rotor1 = rand.nextInt(3); - while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); - rotor3 = 3 - rotor1 - rotor2; + s = addDigit(s, rotor3.getNumber(), 10); + s = addDigit(s, rotor2.getNumber(), 10); + s = addDigit(s, rotor1.getNumber(), 10); - int rot1 = rand.nextInt(26); - int rot2 = rand.nextInt(26); - int rot3 = rand.nextInt(26); - int rotRef = rand.nextInt(26); - int ring1 = rand.nextInt(26); - int ring2 = rand.nextInt(26); - int ring3 = rand.nextInt(26); - int ringRef = rand.nextInt(26); + s = addDigit(s, 5, 12); //Machine #5 - this.rotor1 = Rotor.createRotor(60 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(60 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(60 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(60); - reflector.setRotation(rotRef); - reflector.setRingSetting(ringRef); + save = save+s; + return save; } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G31.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G31.java index 32771c1..3004396 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G31.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G31.java @@ -2,9 +2,6 @@ package de.vanitasvitae.enigmandroid.enigma; import android.util.Log; -import java.security.SecureRandom; -import java.util.Random; - import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; @@ -36,19 +33,24 @@ public class Enigma_G31 extends Enigma protected Reflector reflector; + public Enigma_G31(int off) + { + super(off); + } + public Enigma_G31() { - super(); + super(40); machineType = "G31"; } @Override public void initialize() { this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(40, 0, 0); - this.rotor2 = Rotor.createRotor(41, 0, 0); - this.rotor3 = Rotor.createRotor(42, 0, 0); - this.reflector = Reflector.createReflector(40); + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset + 1, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset + 2, 0, 0); + this.reflector = Reflector.createReflector(machineTypeOffset); } @Override @@ -70,15 +72,12 @@ public class Enigma_G31 extends Enigma } } - @Override - public void randomState() + protected void generateState() { - Random rand = new SecureRandom(); - - int rotor1, rotor2=-1, rotor3=-1; - rotor1 = rand.nextInt(3); - while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); - rotor3 = 3 - rotor1 - rotor2; + int r1, r2=-1, r3=-1; + r1 = rand.nextInt(3); + while(r2 == -1 || r2 == r1) r2 = rand.nextInt(3); + r3 = 3 - r1 - r2; int rot1 = rand.nextInt(26); int rot2 = rand.nextInt(26); @@ -89,10 +88,10 @@ public class Enigma_G31 extends Enigma int ring3 = rand.nextInt(26); int ringRef = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(40 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(40 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(40 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(40); + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); reflector.setRotation(rotRef); reflector.setRingSetting(ringRef); } @@ -160,4 +159,65 @@ public class Enigma_G31 extends Enigma return state; } + + @Override + public void restoreState(String mem) + { + long s = Long.valueOf(mem); + s = removeDigit(s, 12); //Remove machine type + + int r1 = getValue(s, 10); + s = removeDigit(s, 10); + int r2 = getValue(s, 10); + s = removeDigit(s, 10); + int r3 = getValue(s, 10); + s = removeDigit(s, 10); + + int rot1 = getValue(s, 26); + s = removeDigit(s, 26); + int ring1 = getValue(s, 26); + s = removeDigit(s, 26); + int rot2 = getValue(s, 26); + s = removeDigit(s, 26); + int ring2 = getValue(s, 26); + s = removeDigit(s, 26); + int rot3 = getValue(s, 26); + s = removeDigit(s, 26); + int ring3 = getValue(s, 26); + s = removeDigit(s, 26); + int rotRef = getValue(s, 26); + s = removeDigit(s, 26); + int ringRef = getValue(s, 26); + + + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + } + + @Override + public String stateToString() + { + String save = ""; + long s = reflector.getRingSetting(); + s = addDigit(s, reflector.getRotation(), 26); + s = addDigit(s, rotor3.getRingSetting(), 26); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); + + s = addDigit(s, rotor3.getNumber(), 10); + s = addDigit(s, rotor2.getNumber(), 10); + s = addDigit(s, rotor1.getNumber(), 10); + + s = addDigit(s, 3, 12); //Machine #3 + + save = save+s; + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G312.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G312.java index 59140e7..ddb52cd 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G312.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_G312.java @@ -1,12 +1,5 @@ package de.vanitasvitae.enigmandroid.enigma; -import java.security.SecureRandom; -import java.sql.Ref; -import java.util.Random; - -import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; -import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; - /** * Implementation of the Enigma machine of type G31 (Abwehr) * Copyright (C) 2015 Paul Schaub @@ -30,43 +23,30 @@ public class Enigma_G312 extends Enigma_G31 { public Enigma_G312() { - super(); + super(50); machineType = "G312"; } - @Override - public void initialize() - { - this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(50, 0, 0); - this.rotor2 = Rotor.createRotor(51, 0, 0); - this.rotor3 = Rotor.createRotor(52, 0, 0); - this.reflector = Reflector.createReflector(50); - } @Override - public void randomState() + public String stateToString() { - Random rand = new SecureRandom(); + String save = ""; + long s = reflector.getRingSetting(); + s = addDigit(s, reflector.getRotation(), 26); + s = addDigit(s, rotor3.getRingSetting(), 26); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); - int rotor1, rotor2=-1, rotor3=-1; - rotor1 = rand.nextInt(3); - while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); - rotor3 = 3 - rotor1 - rotor2; + s = addDigit(s, rotor3.getNumber(), 10); + s = addDigit(s, rotor2.getNumber(), 10); + s = addDigit(s, rotor1.getNumber(), 10); - int rot1 = rand.nextInt(26); - int rot2 = rand.nextInt(26); - int rot3 = rand.nextInt(26); - int rotRef = rand.nextInt(26); - int ring1 = rand.nextInt(26); - int ring2 = rand.nextInt(26); - int ring3 = rand.nextInt(26); - int ringRef = rand.nextInt(26); + s = addDigit(s, 4, 12); //Machine #4 - this.rotor1 = Rotor.createRotor(50 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(50 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(50 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(50); - reflector.setRotation(rotRef); - reflector.setRingSetting(ringRef); + save = save+s; + return save; } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_I.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_I.java index 0bd597a..2bd8ae6 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_I.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_I.java @@ -1,8 +1,5 @@ package de.vanitasvitae.enigmandroid.enigma; -import java.security.SecureRandom; -import java.util.Random; - import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; @@ -34,6 +31,7 @@ public class Enigma_I extends Enigma protected Reflector reflector; protected Plugboard plugboard; + protected static int machineTypeOffset = 10; public Enigma_I() { @@ -45,10 +43,10 @@ public class Enigma_I extends Enigma public void initialize() { this.plugboard= new Plugboard(); - this.rotor1 = Rotor.createRotor(10, 0, 0); - this.rotor2 = Rotor.createRotor(11, 0, 0); - this.rotor3 = Rotor.createRotor(12, 0, 0); - this.reflector = Reflector.createReflector(10); + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, 0, 0); + this.reflector = Reflector.createReflector(machineTypeOffset); } @Override @@ -67,10 +65,7 @@ public class Enigma_I extends Enigma } @Override - public void randomState() - { - Random rand = new SecureRandom(); - + protected void generateState() { int rotor1, rotor2=-1, rotor3=-1; rotor1 = rand.nextInt(5); while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(5); @@ -84,10 +79,13 @@ public class Enigma_I extends Enigma int ring2 = rand.nextInt(26); int ring3 = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(10 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(10 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(10 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(10 + ref); + this.rotor1 = Rotor.createRotor(machineTypeOffset + rotor1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + rotor2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + rotor3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset + ref); + + this.plugboard = new Plugboard(); + plugboard.setConfiguration(Plugboard.seedToPlugboardConfiguration(rand)); } @Override @@ -151,4 +149,59 @@ public class Enigma_I extends Enigma return state; } + + @Override + public void restoreState(String mem) + { + String plugboardConf = mem.substring(mem.lastIndexOf(":p") + 2); + long s = Long.valueOf(mem.substring(0, mem.indexOf(":p"))); + + s = removeDigit(s, 12); //Remove machine type + int r1 = getValue(s, 10); + s = removeDigit(s, 10); + int r2 = getValue(s, 10); + s = removeDigit(s, 10); + int r3 = getValue(s, 10); + s = removeDigit(s, 10); + int ref = getValue(s, 10); + s = removeDigit(s, 10); + int rot1 = getValue(s, 26); + s = removeDigit(s, 26); + int ring1 = getValue(s, 26); + s = removeDigit(s, 26); + int rot2 = getValue(s, 26); + s = removeDigit(s, 26); + int ring2 = getValue(s, 26); + s = removeDigit(s, 26); + int rot3 = getValue(s, 26); + s = removeDigit(s, 26); + int ring3 = getValue(s, 26); + + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset + ref); + + this.plugboard = new Plugboard(); + plugboard.setConfiguration(Plugboard.stringToConfiguration(plugboardConf)); + } + + @Override + public String stateToString() { + String save = ""; + long s = rotor3.getRingSetting(); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); + s = addDigit(s, rotor3.getNumber(), 10); + s = addDigit(s, rotor2.getNumber(), 10); + s = addDigit(s, rotor1.getNumber(), 10); + s = addDigit(s, 0, 12); //Machine #0 + + save = save+s; + save = save + ":p" + Plugboard.configurationToString(getState().getConfigurationPlugboard()); + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K.java index 271fbbe..8dcb633 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K.java @@ -1,8 +1,12 @@ package de.vanitasvitae.enigmandroid.enigma; +import android.app.Activity; +import android.util.Log; + import java.security.SecureRandom; import java.util.Random; +import de.vanitasvitae.enigmandroid.MainActivity; import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; @@ -34,19 +38,24 @@ public class Enigma_K extends Enigma protected Reflector reflector; + public Enigma_K(int off) + { + super(off); + } + public Enigma_K() { - super(); + super(80); machineType = "K"; } @Override public void initialize() { this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(80, 0, 0); - this.rotor2 = Rotor.createRotor(81, 0, 0); - this.rotor3 = Rotor.createRotor(82, 0, 0); - this.reflector = Reflector.createReflector(80); + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, 0, 0); + this.reflector = Reflector.createReflector(machineTypeOffset); } @Override @@ -65,10 +74,7 @@ public class Enigma_K extends Enigma } @Override - public void randomState() - { - Random rand = new SecureRandom(); - + protected void generateState() { int rotor1, rotor2=-1, rotor3=-1; rotor1 = rand.nextInt(3); while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); @@ -83,10 +89,10 @@ public class Enigma_K extends Enigma int ring3 = rand.nextInt(26); int ringRef = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(80 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(80 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(80 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(80); + this.rotor1 = Rotor.createRotor(machineTypeOffset + rotor1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + rotor2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + rotor3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); reflector.setRotation(rotRef); reflector.setRingSetting(ringRef); } @@ -155,4 +161,61 @@ public class Enigma_K extends Enigma return state; } + + @Override + public void restoreState(String mem) + { + long s = Long.valueOf(mem); + s = removeDigit(s,12); //Remove machine type + int r1 = getValue(s,10); + s = removeDigit(s,10); + int r2 = getValue(s,10); + s = removeDigit(s,10); + int r3 = getValue(s,10); + s = removeDigit(s,10); + + int rot1 = getValue(s,26); + s = removeDigit(s,26); + int ring1 = getValue(s,26); + s = removeDigit(s,26); + int rot2 = getValue(s,26); + s = removeDigit(s,26); + int ring2 = getValue(s,26); + s = removeDigit(s,26); + int rot3 = getValue(s,26); + s = removeDigit(s,26); + int ring3 = getValue(s,26); + s = removeDigit(s,26); + int rotRef = getValue(s,26); + s = removeDigit(s,26); + int ringRef = getValue(s,26); + + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + } + + @Override + public String stateToString() + { + String save = ""; + long t = reflector.getRingSetting(); + t = addDigit(t, reflector.getRotation(), 26); + t = addDigit(t, rotor3.getRingSetting(),26); + t = addDigit(t, rotor3.getRotation(), 26); + t = addDigit(t, rotor2.getRingSetting(),26); + t = addDigit(t, rotor2.getRotation(), 26); + t = addDigit(t, rotor1.getRingSetting(), 26); + t = addDigit(t, rotor1.getRotation(), 26); + t = addDigit(t, rotor3.getNumber(), 10); + t = addDigit(t, rotor2.getNumber(), 10); + t = addDigit(t, rotor1.getNumber(), 10); + t = addDigit(t, 7, 12); //Machine #7 + + save = save+t; + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Airforce.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Airforce.java index c944b5e..6741df1 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Airforce.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Airforce.java @@ -27,131 +27,30 @@ import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; */ public class Enigma_K_Swiss_Airforce extends Enigma_K { - protected Rotor entryWheel; - protected Rotor rotor1; - protected Rotor rotor2; - protected Rotor rotor3; - - protected Reflector reflector; - public Enigma_K_Swiss_Airforce() { - super(); + super(100); machineType = "KSA"; } + @Override - public void initialize() + public String stateToString() { - this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(100, 0, 0); - this.rotor2 = Rotor.createRotor(101, 0, 0); - this.rotor3 = Rotor.createRotor(102, 0, 0); - this.reflector = Reflector.createReflector(100); - } + String save = ""; + long t = reflector.getRingSetting(); + t = addDigit(t, reflector.getRotation(), 26); + t = addDigit(t, rotor3.getRingSetting(),26); + t = addDigit(t, rotor3.getRotation(), 26); + t = addDigit(t, rotor2.getRingSetting(),26); + t = addDigit(t, rotor2.getRotation(), 26); + t = addDigit(t, rotor1.getRingSetting(), 26); + t = addDigit(t, rotor1.getRotation(), 26); + t = addDigit(t, rotor3.getNumber(), 10); + t = addDigit(t, rotor2.getNumber(), 10); + t = addDigit(t, rotor1.getNumber(), 10); + t = addDigit(t, 9, 12); //Machine #9 - @Override - public void nextState() - { - rotor1.rotate(); - if (rotor1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly)) - { - rotor2.rotate(); - this.doAnomaly = rotor2.doubleTurnAnomaly(); - if (rotor2.isAtTurnoverPosition()) - { - rotor3.rotate(); - } - } - } - - @Override - public void randomState() - { - Random rand = new SecureRandom(); - - int rotor1, rotor2=-1, rotor3=-1; - rotor1 = rand.nextInt(3); - while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); - rotor3 = 3 - rotor1 - rotor2; - - int rot1 = rand.nextInt(26); - int rot2 = rand.nextInt(26); - int rot3 = rand.nextInt(26); - int rotRef = rand.nextInt(26); - int ring1 = rand.nextInt(26); - int ring2 = rand.nextInt(26); - int ring3 = rand.nextInt(26); - int ringRef = rand.nextInt(26); - - this.rotor1 = Rotor.createRotor(100 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(100 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(100 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(100); - reflector.setRotation(rotRef); - reflector.setRingSetting(ringRef); - } - - @Override - public char encryptChar(char k) { - nextState(); - int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.) - //Encryption - //forward direction - x = entryWheel.encryptForward(x); - x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting()); - x = rotor1.encryptForward(x); - x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting()); - x = rotor2.encryptForward(x); - x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting()); - x = rotor3.encryptForward(x); - x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting()); - //backward direction - x = reflector.encrypt(x); - x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting()); - x = rotor3.encryptBackward(x); - x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting()); - x = rotor2.encryptBackward(x); - x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting()); - x = rotor1.encryptBackward(x); - x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting()); - x = entryWheel.encryptBackward(x); - return (char) (x + 65); //Add Offset again, cast back to char and return - } - - @Override - public void setState(EnigmaStateBundle state) - { - this.entryWheel = Rotor.createRotor(state.getTypeEntryWheel(), 0, 0); - this.rotor1 = Rotor.createRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1()); - this.rotor2 = Rotor.createRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2()); - this.rotor3 = Rotor.createRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3()); - this.reflector = Reflector.createReflector(state.getTypeReflector()); - this.reflector.setRotation(state.getRotationReflector()); - this.reflector.setRingSetting(state.getRingSettingReflector()); - } - - @Override - public EnigmaStateBundle getState() { - EnigmaStateBundle state = new EnigmaStateBundle(); - - state.setTypeEntryWheel(entryWheel.getNumber()); - - state.setTypeRotor1(rotor1.getNumber()); - state.setTypeRotor2(rotor2.getNumber()); - state.setTypeRotor3(rotor3.getNumber()); - - state.setRotationRotor1(rotor1.getRotation()); - state.setRotationRotor2(rotor2.getRotation()); - state.setRotationRotor3(rotor3.getRotation()); - - state.setRingSettingRotor1(rotor1.getRingSetting()); - state.setRingSettingRotor2(rotor2.getRingSetting()); - state.setRingSettingRotor3(rotor3.getRingSetting()); - - state.setTypeReflector(reflector.getNumber()); - state.setRotationReflector(reflector.getRotation()); - state.setRingSettingReflector(reflector.getRingSetting()); - - return state; + save = save+t; + return save; } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Standard.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Standard.java index 5e7d919..a25a10b 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Standard.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_K_Swiss_Standard.java @@ -27,131 +27,31 @@ import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; */ public class Enigma_K_Swiss_Standard extends Enigma_K { - protected Rotor entryWheel; - protected Rotor rotor1; - protected Rotor rotor2; - protected Rotor rotor3; - - protected Reflector reflector; - public Enigma_K_Swiss_Standard() { - super(); + super(90); machineType = "KS"; } + @Override - public void initialize() + public String stateToString() { - this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(90, 0, 0); - this.rotor2 = Rotor.createRotor(91, 0, 0); - this.rotor3 = Rotor.createRotor(92, 0, 0); - this.reflector = Reflector.createReflector(90); + String save = ""; + long t = reflector.getRingSetting(); + t = addDigit(t, reflector.getRotation(), 26); + t = addDigit(t, rotor3.getRingSetting(),26); + t = addDigit(t, rotor3.getRotation(), 26); + t = addDigit(t, rotor2.getRingSetting(),26); + t = addDigit(t, rotor2.getRotation(), 26); + t = addDigit(t, rotor1.getRingSetting(), 26); + t = addDigit(t, rotor1.getRotation(), 26); + t = addDigit(t, rotor3.getNumber(), 10); + t = addDigit(t, rotor2.getNumber(), 10); + t = addDigit(t, rotor1.getNumber(), 10); + t = addDigit(t, 8, 12); //Machine #8 + + save = save+t; + return save; } - @Override - public void nextState() - { - rotor1.rotate(); - if (rotor1.isAtTurnoverPosition() || (this.doAnomaly && prefAnomaly)) - { - rotor2.rotate(); - this.doAnomaly = rotor2.doubleTurnAnomaly(); - if (rotor2.isAtTurnoverPosition()) - { - rotor3.rotate(); - } - } - } - - @Override - public void randomState() - { - Random rand = new SecureRandom(); - - int rotor1, rotor2=-1, rotor3=-1; - rotor1 = rand.nextInt(3); - while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); - rotor3 = 3 - rotor1 - rotor2; - - int rot1 = rand.nextInt(26); - int rot2 = rand.nextInt(26); - int rot3 = rand.nextInt(26); - int rotRef = rand.nextInt(26); - int ring1 = rand.nextInt(26); - int ring2 = rand.nextInt(26); - int ring3 = rand.nextInt(26); - int ringRef = rand.nextInt(26); - - this.rotor1 = Rotor.createRotor(90 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(90 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(90 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(90); - reflector.setRotation(rotRef); - reflector.setRingSetting(ringRef); - } - - @Override - public char encryptChar(char k) { - nextState(); - int x = ((int) k)-65; //Cast to int and remove Unicode Offset (A=65 in Unicode.) - //Encryption - //forward direction - x = entryWheel.encryptForward(x); - x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting()); - x = rotor1.encryptForward(x); - x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting() + rotor2.getRotation() - rotor2.getRingSetting()); - x = rotor2.encryptForward(x); - x = rotor1.normalize(x - rotor2.getRotation() + rotor2.getRingSetting() + rotor3.getRotation() - rotor3.getRingSetting()); - x = rotor3.encryptForward(x); - x = rotor1.normalize(x - rotor3.getRotation() + rotor3.getRingSetting() + reflector.getRotation() - reflector.getRingSetting()); - //backward direction - x = reflector.encrypt(x); - x = rotor1.normalize(x + rotor3.getRotation() - rotor3.getRingSetting() - reflector.getRotation() + reflector.getRingSetting()); - x = rotor3.encryptBackward(x); - x = rotor1.normalize(x + rotor2.getRotation() - rotor2.getRingSetting() - rotor3.getRotation() + rotor3.getRingSetting()); - x = rotor2.encryptBackward(x); - x = rotor1.normalize(x + rotor1.getRotation() - rotor1.getRingSetting() - rotor2.getRotation() + rotor2.getRingSetting()); - x = rotor1.encryptBackward(x); - x = rotor1.normalize(x - rotor1.getRotation() + rotor1.getRingSetting()); - x = entryWheel.encryptBackward(x); - return (char) (x + 65); //Add Offset again, cast back to char and return - } - - @Override - public void setState(EnigmaStateBundle state) - { - this.entryWheel = Rotor.createRotor(state.getTypeEntryWheel(), 0, 0); - this.rotor1 = Rotor.createRotor(state.getTypeRotor1(), state.getRotationRotor1(), state.getRingSettingRotor1()); - this.rotor2 = Rotor.createRotor(state.getTypeRotor2(), state.getRotationRotor2(), state.getRingSettingRotor2()); - this.rotor3 = Rotor.createRotor(state.getTypeRotor3(), state.getRotationRotor3(), state.getRingSettingRotor3()); - this.reflector = Reflector.createReflector(state.getTypeReflector()); - this.reflector.setRotation(state.getRotationReflector()); - this.reflector.setRingSetting(state.getRingSettingReflector()); - } - - @Override - public EnigmaStateBundle getState() { - EnigmaStateBundle state = new EnigmaStateBundle(); - - state.setTypeEntryWheel(entryWheel.getNumber()); - - state.setTypeRotor1(rotor1.getNumber()); - state.setTypeRotor2(rotor2.getNumber()); - state.setTypeRotor3(rotor3.getNumber()); - - state.setRotationRotor1(rotor1.getRotation()); - state.setRotationRotor2(rotor2.getRotation()); - state.setRotationRotor3(rotor3.getRotation()); - - state.setRingSettingRotor1(rotor1.getRingSetting()); - state.setRingSettingRotor2(rotor2.getRingSetting()); - state.setRingSettingRotor3(rotor3.getRingSetting()); - - state.setTypeReflector(reflector.getNumber()); - state.setRotationReflector(reflector.getRotation()); - state.setRingSettingReflector(reflector.getRingSetting()); - - return state; - } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M3.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M3.java index 26a95be..d57f2e8 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M3.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M3.java @@ -28,25 +28,16 @@ import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; */ public class Enigma_M3 extends Enigma_I { + protected static int machineTypeOffset = 20; + public Enigma_M3() { + super(); machineType = "M3"; } - @Override - public void initialize() - { - this.plugboard = new Plugboard(); - this.rotor1 = Rotor.createRotor(20, 0, 0); - this.rotor2 = Rotor.createRotor(21, 0, 0); - this.rotor3 = Rotor.createRotor(22, 0, 0); - this.reflector = Reflector.createReflector(20); - } @Override - public void randomState() - { - Random rand = new SecureRandom(); - + protected void generateState() { int rotor1, rotor2=-1, rotor3=-1; rotor1 = rand.nextInt(8); while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(8); @@ -60,9 +51,31 @@ public class Enigma_M3 extends Enigma_I int ring2 = rand.nextInt(26); int ring3 = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(20 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(20 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(20 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(20 + ref); + this.rotor1 = Rotor.createRotor(machineTypeOffset + rotor1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + rotor2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + rotor3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset + ref); + + this.plugboard = new Plugboard(); + plugboard.setConfiguration(Plugboard.seedToPlugboardConfiguration(rand)); + } + + @Override + public String stateToString() { + String save = ""; + long s = rotor3.getRingSetting(); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); + s = addDigit(s, rotor3.getNumber(), 10); + s = addDigit(s, rotor2.getNumber(), 10); + s = addDigit(s, rotor1.getNumber(), 10); + s = addDigit(s, 1, 12); //Machine #1 + + save = save+s; + save = save + ":p" + Plugboard.configurationToString(getState().getConfigurationPlugboard()); + return save; } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M4.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M4.java index 5f1c082..63a6337 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M4.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_M4.java @@ -3,6 +3,7 @@ package de.vanitasvitae.enigmandroid.enigma; import java.security.SecureRandom; import java.util.Random; +import de.vanitasvitae.enigmandroid.MainActivity; import de.vanitasvitae.enigmandroid.enigma.rotors.Reflector; import de.vanitasvitae.enigmandroid.enigma.rotors.Rotor; @@ -36,6 +37,8 @@ public class Enigma_M4 extends Enigma private Plugboard plugboard; + protected static int machineTypeOffset = 30; + public Enigma_M4() { super(); @@ -46,12 +49,13 @@ public class Enigma_M4 extends Enigma public void initialize() { this.plugboard = new Plugboard(); - this.rotor1 = Rotor.createRotor(30, 0, 0); - this.rotor2 = Rotor.createRotor(31, 0, 0); - this.rotor3 = Rotor.createRotor(32, 0, 0); - this.rotor4 = Rotor.createRotor(38, 0, 0); - this.reflector = Reflector.createReflector(30); - this.prefAnomaly = true; + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, 0, 0); + this.rotor4 = Rotor.createRotor(machineTypeOffset + 8, 0, 0); + this.reflector = Reflector.createReflector(machineTypeOffset); + this.prefAnomaly = ((MainActivity) MainActivity.ActivitySingleton.getInstance() + .getActivity()).getPrefAnomaly(); } @Override @@ -79,17 +83,14 @@ public class Enigma_M4 extends Enigma } @Override - public void randomState() - { - Random rand = new SecureRandom(); - - int rotor1, rotor2=-1, rotor3=-1; - int rotor4; + protected void generateState() { + int r1, r2=-1, r3=-1; + int r4; int ref; - rotor1 = rand.nextInt(8); - while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(8); - while(rotor3 == -1 || rotor3 == rotor2 || rotor3 == rotor1) rotor3 = rand.nextInt(8); - rotor4 = rand.nextInt(2); + r1 = rand.nextInt(8); + while(r2 == -1 || r2 == r1) r2 = rand.nextInt(8); + while(r3 == -1 || r3 == r2 || r3 == r1) r3 = rand.nextInt(8); + r4 = rand.nextInt(2); ref = rand.nextInt(2); int rot1 = rand.nextInt(26); @@ -103,13 +104,17 @@ public class Enigma_M4 extends Enigma int ring4 = rand.nextInt(26); int ringRef = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(30 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(30 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(30 + rotor3, rot3, ring3); - this.rotor4 = Rotor.createRotor(38 + rotor4, rot4, ring4); - this.reflector = Reflector.createReflector(30 + ref); - reflector.setRotation(rotRef); - reflector.setRingSetting(ringRef); + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.rotor4 = Rotor.createRotor(machineTypeOffset + 8 + r4, rot4, ring4); + + this.reflector = Reflector.createReflector(machineTypeOffset + ref); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + + this.plugboard = new Plugboard(); + this.plugboard.setConfiguration(Plugboard.seedToPlugboardConfiguration(rand)); } @Override @@ -189,4 +194,82 @@ public class Enigma_M4 extends Enigma return state; } + + @Override + public void restoreState(String mem) + { + String plugboardConf = mem.substring(mem.lastIndexOf(":p") + 2); + long s = Long.valueOf(mem.substring(0, mem.indexOf(":p"))); + + s = (s-(s%12))/12; //Remove machine type + + int r1 = getValue(s, 10); + s = removeDigit(s, 10); + int r2 = getValue(s, 10); + s = removeDigit(s,10); + int r3 = getValue(s, 10); + s = removeDigit(s,10); + int r4 = getValue(s, 10); + s = removeDigit(s,10); + int ref = getValue(s, 10); + s = removeDigit(s,10); + + int rot1 = getValue(s, 26); + s = removeDigit(s,26); + int ring1 = getValue(s, 26); + s = removeDigit(s,26); + int rot2 = getValue(s, 26); + s = removeDigit(s,26); + int ring2 = getValue(s, 26); + s = removeDigit(s,26); + int rot3 = getValue(s, 26); + s = removeDigit(s,26); + int ring3 = getValue(s, 26); + s = removeDigit(s,26); + int rot4 = getValue(s, 26); + s = removeDigit(s,26); + int ring4 = getValue(s, 26); + s = removeDigit(s,26); + int rotRef = getValue(s, 26); + s = removeDigit(s,26); + int ringRef = getValue(s, 26); + + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.rotor4 = Rotor.createRotor(machineTypeOffset + r4, rot4, ring4); + this.reflector = Reflector.createReflector(machineTypeOffset + ref); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + + this.plugboard = new Plugboard(); + plugboard.setConfiguration(Plugboard.stringToConfiguration(plugboardConf)); + } + + @Override + public String stateToString() { + String save = ""; + long s = reflector.getRingSetting(); + s = addDigit(s, reflector.getRotation(), 26); + s = addDigit(s, rotor4.getRingSetting(), 26); + s = addDigit(s, rotor4.getRotation(), 26); + s = addDigit(s, rotor3.getRingSetting(), 26); + s = addDigit(s, rotor3.getRotation(), 26); + s = addDigit(s, rotor2.getRingSetting(), 26); + s = addDigit(s, rotor2.getRotation(), 26); + s = addDigit(s, rotor1.getRingSetting(), 26); + s = addDigit(s, rotor1.getRotation(), 26); + + s = addDigit(s, reflector.getNumber(), 10); + s = addDigit(s, rotor4.getNumber(), 10); + s = addDigit(s, rotor3.getNumber(), 10); + s = addDigit(s, rotor2.getNumber(), 10); + s = addDigit(s, rotor1.getNumber(), 10); + + s = addDigit(s, 2, 12); + + save = save+s; + save = save + ":p" + Plugboard.configurationToString(getState().getConfigurationPlugboard()); + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_R.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_R.java index 8f2826b..5c29fcd 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_R.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_R.java @@ -34,6 +34,8 @@ public class Enigma_R extends Enigma protected Reflector reflector; + protected static int machineTypeOffset = 110; + public Enigma_R() { super(); @@ -43,10 +45,10 @@ public class Enigma_R extends Enigma public void initialize() { this.entryWheel = Rotor.createRotor(1, 0, 0); - this.rotor1 = Rotor.createRotor(110, 0, 0); - this.rotor2 = Rotor.createRotor(111, 0, 0); - this.rotor3 = Rotor.createRotor(112, 0, 0); - this.reflector = Reflector.createReflector(110); + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, 0, 0); + this.reflector = Reflector.createReflector(machineTypeOffset); } @Override @@ -65,10 +67,8 @@ public class Enigma_R extends Enigma } @Override - public void randomState() + protected void generateState() { - Random rand = new SecureRandom(); - int rotor1, rotor2=-1, rotor3=-1; rotor1 = rand.nextInt(3); while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(3); @@ -83,10 +83,10 @@ public class Enigma_R extends Enigma int ring3 = rand.nextInt(26); int ringRef = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(110 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(110 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(110 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(110); + this.rotor1 = Rotor.createRotor(machineTypeOffset + rotor1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + rotor2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + rotor3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); reflector.setRotation(rotRef); reflector.setRingSetting(ringRef); } @@ -154,4 +154,61 @@ public class Enigma_R extends Enigma return state; } + + @Override + public void restoreState(String mem) + { + long s = Long.valueOf(mem); + s = removeDigit(s,12); //Remove machine type + int r1 = getValue(s,10); + s = removeDigit(s,10); + int r2 = getValue(s,10); + s = removeDigit(s,10); + int r3 = getValue(s,10); + s = removeDigit(s,10); + + int rot1 = getValue(s,26); + s = removeDigit(s,26); + int ring1 = getValue(s,26); + s = removeDigit(s,26); + int rot2 = getValue(s,26); + s = removeDigit(s,26); + int ring2 = getValue(s,26); + s = removeDigit(s,26); + int rot3 = getValue(s,26); + s = removeDigit(s,26); + int ring3 = getValue(s,26); + s = removeDigit(s,26); + int rotRef = getValue(s,26); + s = removeDigit(s,26); + int ringRef = getValue(s,26); + + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + } + + @Override + public String stateToString() + { + String save = ""; + long t = reflector.getRingSetting(); + t = addDigit(t, reflector.getRotation(), 26); + t = addDigit(t, rotor3.getRingSetting(),26); + t = addDigit(t, rotor3.getRotation(), 26); + t = addDigit(t, rotor2.getRingSetting(),26); + t = addDigit(t, rotor2.getRotation(), 26); + t = addDigit(t, rotor1.getRingSetting(), 26); + t = addDigit(t, rotor1.getRotation(), 26); + t = addDigit(t, rotor3.getNumber(), 10); + t = addDigit(t, rotor2.getNumber(), 10); + t = addDigit(t, rotor1.getNumber(), 10); + t = addDigit(t, 10, 12); //Machine #10 + + save = save+t; + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_T.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_T.java index e10b96d..26383f0 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_T.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Enigma_T.java @@ -35,6 +35,8 @@ public class Enigma_T extends Enigma protected Rotor rotor3; protected Reflector reflector; + protected static int machineTypeOffset = 120; + public Enigma_T() { super(); @@ -44,10 +46,10 @@ public class Enigma_T extends Enigma @Override public void initialize() { this.entryWheel = Rotor.createRotor(2,0,0); - this.rotor1 = Rotor.createRotor(120, 0, 0); - this.rotor2 = Rotor.createRotor(121, 0, 0); - this.rotor3 = Rotor.createRotor(122, 0, 0); - this.reflector = Reflector.createReflector(120); + this.rotor1 = Rotor.createRotor(machineTypeOffset, 0, 0); + this.rotor2 = Rotor.createRotor(machineTypeOffset+1, 0, 0); + this.rotor3 = Rotor.createRotor(machineTypeOffset+2, 0, 0); + this.reflector = Reflector.createReflector(machineTypeOffset); } @Override @@ -66,10 +68,7 @@ public class Enigma_T extends Enigma } @Override - public void randomState() - { - Random rand = new SecureRandom(); - + protected void generateState() { int rotor1, rotor2=-1, rotor3=-1; rotor1 = rand.nextInt(8); while(rotor2 == -1 || rotor2 == rotor1) rotor2 = rand.nextInt(8); @@ -84,10 +83,10 @@ public class Enigma_T extends Enigma int ring3 = rand.nextInt(26); int ringRef = rand.nextInt(26); - this.rotor1 = Rotor.createRotor(120 + rotor1, rot1, ring1); - this.rotor2 = Rotor.createRotor(120 + rotor2, rot2, ring2); - this.rotor3 = Rotor.createRotor(120 + rotor3, rot3, ring3); - this.reflector = Reflector.createReflector(120); + this.rotor1 = Rotor.createRotor(machineTypeOffset + rotor1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + rotor2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + rotor3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); reflector.setRotation(rotRef); reflector.setRingSetting(ringRef); } @@ -155,5 +154,60 @@ public class Enigma_T extends Enigma return state; } + @Override + public void restoreState(String mem) + { + long s = Long.valueOf(mem); + s = removeDigit(s,12); //Remove machine type + int r1 = getValue(s,10); + s = removeDigit(s,10); + int r2 = getValue(s,10); + s = removeDigit(s,10); + int r3 = getValue(s,10); + s = removeDigit(s,10); + int rot1 = getValue(s,26); + s = removeDigit(s,26); + int ring1 = getValue(s,26); + s = removeDigit(s,26); + int rot2 = getValue(s,26); + s = removeDigit(s,26); + int ring2 = getValue(s,26); + s = removeDigit(s,26); + int rot3 = getValue(s,26); + s = removeDigit(s,26); + int ring3 = getValue(s,26); + s = removeDigit(s,26); + int rotRef = getValue(s,26); + s = removeDigit(s,26); + int ringRef = getValue(s,26); + + this.rotor1 = Rotor.createRotor(machineTypeOffset + r1, rot1, ring1); + this.rotor2 = Rotor.createRotor(machineTypeOffset + r2, rot2, ring2); + this.rotor3 = Rotor.createRotor(machineTypeOffset + r3, rot3, ring3); + this.reflector = Reflector.createReflector(machineTypeOffset); + this.reflector.setRotation(rotRef); + this.reflector.setRingSetting(ringRef); + } + + @Override + public String stateToString() + { + String save = ""; + long t = reflector.getRingSetting(); + t = addDigit(t, reflector.getRotation(), 26); + t = addDigit(t, rotor3.getRingSetting(),26); + t = addDigit(t, rotor3.getRotation(), 26); + t = addDigit(t, rotor2.getRingSetting(),26); + t = addDigit(t, rotor2.getRotation(), 26); + t = addDigit(t, rotor1.getRingSetting(), 26); + t = addDigit(t, rotor1.getRotation(), 26); + t = addDigit(t, rotor3.getNumber(), 10); + t = addDigit(t, rotor2.getNumber(), 10); + t = addDigit(t, rotor1.getNumber(), 10); + t = addDigit(t, 11, 12); //Machine #11 + + save = save+t; + return save; + } } diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Plugboard.java b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Plugboard.java index affdc50..39f55aa 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Plugboard.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/enigma/Plugboard.java @@ -1,5 +1,9 @@ package de.vanitasvitae.enigmandroid.enigma; +import java.util.Random; + +import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer; + /** * Plugboard of the enigma * Copyright (C) 2015 Paul Schaub @@ -53,4 +57,115 @@ public class Plugboard { return plugs[(input+plugs.length)%plugs.length]; } + + /** + * Interpret a String of Pairs as a configuration for the plugboard + * Any char with an even index is connected to the successor. + * in must not contain duplicates! + * @param in String representation of pairs (eg. AXBHCS...) + * @return connections as int[] + */ + public static int[] stringToConfiguration(String in) + { + String pairs = trimString(new InputPreparer.RemoveIllegalCharacters().prepareString(in)); + int[] out = empty; + //Check if in is too long or odd + if(pairs.length() > 26 || pairs.length()/2 == (pairs.length()-1)/2) + { + //Odd length. remove last char. Information loss! + pairs = pairs.substring(0,pairs.length()-1); + } + //Modify out + for(int i=0; i 0) positive.setEnabled(true); + else positive.setEnabled(false); + } + }); + } + + public void showDialog() + { + + AlertDialog.Builder builder = new AlertDialog.Builder(main); + builder.setTitle(R.string.hint_passphrase); + Dialog d = builder.setView(passphraseDialogView) + .setCancelable(true) + .setPositiveButton(R.string.dialog_positiv, new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog, int id) + { + String pass = passphrase.getText().toString(); + main.createStateFromSeed(pass); + String message = main.getResources().getString(R.string.dialog_passphrase_set) + +" \'" + pass + "\'"; + Toast.makeText(main, message, Toast.LENGTH_LONG).show(); + } + }) + .setNegativeButton(R.string.dialog_negativ, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + Toast.makeText(main, R.string.dialog_abort, + Toast.LENGTH_SHORT).show(); + } + }).create(); + d.show(); + positive = ((AlertDialog)d).getButton(AlertDialog.BUTTON_POSITIVE); + positive.setEnabled(false); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/vanitasvitae/enigmandroid/layout/PluggableDialogBuilder.java b/app/src/main/java/de/vanitasvitae/enigmandroid/layout/PluggableDialogBuilder.java index 8062c2b..eaf4895 100644 --- a/app/src/main/java/de/vanitasvitae/enigmandroid/layout/PluggableDialogBuilder.java +++ b/app/src/main/java/de/vanitasvitae/enigmandroid/layout/PluggableDialogBuilder.java @@ -3,7 +3,6 @@ package de.vanitasvitae.enigmandroid.layout; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; -import android.graphics.drawable.Drawable; import android.util.Log; import android.view.View; import android.view.WindowManager; @@ -13,7 +12,6 @@ import android.widget.Toast; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; -import java.util.Objects; import de.vanitasvitae.enigmandroid.MainActivity; import de.vanitasvitae.enigmandroid.R; @@ -45,6 +43,9 @@ public class PluggableDialogBuilder protected MainActivity main; protected EnigmaStateBundle state; + protected boolean allowIncompleteConnections; + protected Button positive; + protected HashSet colors; protected int previouslyPressedButton = -1; @@ -59,6 +60,7 @@ public class PluggableDialogBuilder public void showDialogPlugboard() { + allowIncompleteConnections = true; restoreConfigurationPlugboard(); AlertDialog.Builder adb = new AlertDialog.Builder(main); adb.setTitle(R.string.title_plugboard_dialog); @@ -71,6 +73,7 @@ public class PluggableDialogBuilder plugs[i] = buttons.get(i).getConnectedButton(); } state.setConfigurationPlugboard(plugs); + main.onDialogFinished(state); Toast.makeText(main.getApplication(), R.string.dialog_plugboard_set, Toast.LENGTH_SHORT).show(); } }) @@ -92,6 +95,7 @@ public class PluggableDialogBuilder public void showDialogReflector() { + allowIncompleteConnections = false; restoreConfigurationReflector(); AlertDialog.Builder adb = new AlertDialog.Builder(main); adb.setTitle(R.string.title_reflector_dialog); @@ -104,6 +108,7 @@ public class PluggableDialogBuilder plugs[i] = buttons.get(i).getConnectedButton(); } state.setConfigurationReflector(plugs); + main.onDialogFinished(state); Toast.makeText(main.getApplication(), R.string.dialog_reflector_set, Toast.LENGTH_SHORT).show(); } }) @@ -120,6 +125,11 @@ public class PluggableDialogBuilder lp.width = WindowManager.LayoutParams.MATCH_PARENT; lp.height = WindowManager.LayoutParams.WRAP_CONTENT; d.show(); + positive = ((AlertDialog)d).getButton(AlertDialog.BUTTON_POSITIVE); + if(!allConnectionsDone()) + { + positive.setEnabled(false); + } d.getWindow().setAttributes(lp); } public void initializeLayout() @@ -186,6 +196,16 @@ public class PluggableDialogBuilder } } + protected boolean allConnectionsDone() + { + for(int i=0; i + + + + + diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml index 158c299..4cf1327 100755 --- a/app/src/main/res/menu/main.xml +++ b/app/src/main/res/menu/main.xml @@ -2,29 +2,50 @@ xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity" > + + - + + + + + + + + + - + + android:title="@string/action_settings" + android:orderInCategory="102" + android:showAsAction="ifRoom" /> + + android:title="@string/title_action_about" + android:orderInCategory="103" + android:showAsAction="ifRoom" /> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0d03706..c7a1969 100755 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -5,6 +5,9 @@ Version Zurücksetzen Zufällige Konfiguration + Lese Konfiguration aus QR-Code + Teile Konfiguration per QR-Code + Konfiguration aus Schlüsselwort Einstellungen Ringstellung Senden @@ -24,13 +27,14 @@ Position\nUmkehr-\nWalze Position\nWalze 4 Verkabelung Umkehrwalze + Passphrase eingeben Ver-/Entschlüsseln Fehler: Fehlerhafte Steckerbrettkonfiguration. Kann Stecker nicht setzen: Fehler: Einer oder mehrere dieser Stecker sind bereits in Benutzung: Nachricht ist leer. Ringstellungen - Steckbrett-\nverbindungen + Steckbrett-\nVerbindungen Verkabelung Umkehrwalze OK Abbrechen @@ -38,6 +42,7 @@ Setze Ringe auf Umkehrwalze verkabelt. Steckbrett gesteckert. + Generiere Konfiguration aus Schlüsselwort Keine Änderungen Enigma zurückgesetzt Enigma auf zufällige Konfiguration gesetzt diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8d09fb6..ff2b69f 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,6 +6,9 @@ Version Reset Random configuration + Read configuration from QR-Code + Share configuration via QR-Code + Create configuration from passphrase Ring-Settings Settings Send @@ -25,6 +28,7 @@ Position\nReflector Position\nRotor 4 Wiring Reflector + Enter passphrase En-/Decrypt! Error: Can\'t interpret plugboard input. Unable to plug @@ -39,6 +43,7 @@ Set Ring-Settings to Rewired Reflector. Plugged Plugboard. + Generate configuration from passphrase No changes Enigma reset Enigma set to random configuration