diff --git a/.idea/modules.xml b/.idea/modules.xml
index c298687..24ae196 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,8 +2,8 @@
-
+
\ No newline at end of file
diff --git a/MISPauth .pdf b/MISPauth .pdf
deleted file mode 100644
index d2e41b2..0000000
Binary files a/MISPauth .pdf and /dev/null differ
diff --git a/Screenshots/main-screen.png b/Screenshots/main-screen.png
deleted file mode 100755
index 9861fab..0000000
Binary files a/Screenshots/main-screen.png and /dev/null differ
diff --git a/Screenshots/my-org-screen.png b/Screenshots/my-org-screen.png
deleted file mode 100755
index 7cded1f..0000000
Binary files a/Screenshots/my-org-screen.png and /dev/null differ
diff --git a/Screenshots/scan-screen.png b/Screenshots/scan-screen.png
deleted file mode 100755
index 43043ab..0000000
Binary files a/Screenshots/scan-screen.png and /dev/null differ
diff --git a/Screenshots/share-screen.png b/Screenshots/share-screen.png
deleted file mode 100755
index 50fa435..0000000
Binary files a/Screenshots/share-screen.png and /dev/null differ
diff --git a/Screenshots/upload-screen.png b/Screenshots/upload-screen.png
deleted file mode 100755
index c4dadfc..0000000
Binary files a/Screenshots/upload-screen.png and /dev/null differ
diff --git a/app/build.gradle b/app/build.gradle
index 347c82a..85861d0 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,10 +2,10 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 27
- buildToolsVersion "27.0.3"
+ buildToolsVersion "28.0.0"
defaultConfig {
applicationId "de.overview.wg.its.mispauth"
- minSdkVersion 21
+ minSdkVersion 23
targetSdkVersion 27
versionCode 1
versionName "1.0"
@@ -17,6 +17,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ }
}
dependencies {
@@ -30,6 +33,13 @@ dependencies {
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.volley:volley:1.1.0'
- implementation 'com.github.kenglxn.QRGen:android:2.4.0'
+ implementation 'com.github.kenglxn.QRGen:android:2.5.0'
+ implementation group: 'org.mongodb', name: 'bson', version: '3.8.0'
+ implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
+
+
+
implementation 'com.google.android.gms:play-services-vision:15.0.2'
+ implementation 'com.android.support:gridlayout-v7:27.1.1'
+ implementation 'com.ernestoyaquello.stepperform:vertical-stepper-form:0.9.9'
}
diff --git a/app/src/androidTest/java/de/overview/wg/its/mispauth/ExampleInstrumentedTest.java b/app/src/androidTest/java/de/overview/wg/its/mispauth/ExampleInstrumentedTest.java
index 4435194..0f87c70 100644
--- a/app/src/androidTest/java/de/overview/wg/its/mispauth/ExampleInstrumentedTest.java
+++ b/app/src/androidTest/java/de/overview/wg/its/mispauth/ExampleInstrumentedTest.java
@@ -16,11 +16,11 @@ import static org.junit.Assert.*;
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() throws Exception {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
- assertEquals("de.overview.wg.its.mispauth", appContext.getPackageName());
- }
+ assertEquals("de.overview.wg.its.mispauth", appContext.getPackageName());
+ }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5e7973a..0f8a22f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,8 +12,9 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
-
-
+
@@ -22,15 +23,19 @@
+ android:screenOrientation="portrait"
+ android:name=".SyncActivity"
+ android:label="Sync"
+ android:parentActivityName=".MainActivity"
+ android:theme="@style/AppTheme.Fullscreen">
+
+ android:name=".CredentialsActivity"
+ android:label="@string/credentials_activity"
+ android:parentActivityName=".MainActivity"/>
+
\ No newline at end of file
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/CredentialsActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/CredentialsActivity.java
new file mode 100644
index 0000000..9480de9
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/CredentialsActivity.java
@@ -0,0 +1,417 @@
+package de.overview.wg.its.mispauth;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.design.widget.TextInputLayout;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import com.android.volley.VolleyError;
+import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
+import de.overview.wg.its.mispauth.auxiliary.ReadableError;
+import de.overview.wg.its.mispauth.cam.DialogFactory;
+import de.overview.wg.its.mispauth.model.Organisation;
+import de.overview.wg.its.mispauth.model.User;
+import de.overview.wg.its.mispauth.network.MispRequest;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+@SuppressWarnings("ConstantConditions")
+@SuppressLint("SetTextI18n")
+public class CredentialsActivity extends AppCompatActivity implements View.OnClickListener {
+
+ private boolean changesMade;
+ private boolean saveAuthkey, saveAuthkeyPrefSet;
+
+ private TextInputLayout urlLayout, apiLayout;
+ private TextView emptyView;
+ private ViewGroup organisationView;
+ private ProgressBar progressBar;
+
+ private Organisation myOrganisation;
+ private User myUser;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_credentials);
+
+ initializeViews();
+ loadPreferences();
+ addSaveChangesListener();
+ }
+
+ private void initializeViews() {
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+
+ progressBar = findViewById(R.id.progressBar);
+
+ urlLayout = findViewById(R.id.input_layout_server_url);
+ apiLayout = findViewById(R.id.input_layout_api_key);
+
+ FloatingActionButton fab = findViewById(R.id.fab_download_own_org_info);
+ fab.setOnClickListener(this);
+
+ emptyView = findViewById(R.id.empty);
+ organisationView = findViewById(R.id.myOrganisationView);
+
+ }
+
+ private void loadPreferences() {
+
+ PreferenceManager preferenceManager = PreferenceManager.Instance(this);
+
+ saveAuthkeyPrefSet = preferenceManager.saveAuthkeyEnabledExists();
+ saveAuthkey = preferenceManager.saveAuthkeyEnabled();
+
+ urlLayout.getEditText().setText(preferenceManager.getMyServerUrl());
+ apiLayout.getEditText().setText(preferenceManager.getMyServerApiKey());
+
+ myOrganisation = preferenceManager.getMyOrganisation();
+
+ if (myOrganisation == null) {
+
+ emptyView.setVisibility(View.VISIBLE);
+ organisationView.setVisibility(View.GONE);
+
+ } else {
+
+ emptyView.setVisibility(View.GONE);
+ organisationView.setVisibility(View.VISIBLE);
+
+ visualizeOrganisation();
+
+ }
+ }
+
+ private void savePreferences() {
+
+ PreferenceManager preferenceManager = PreferenceManager.Instance(this);
+
+ preferenceManager.setMyServerUrl(urlLayout.getEditText().getText().toString());
+ preferenceManager.setSaveAuthkeyEnabled(saveAuthkey);
+
+ if (saveAuthkey) {
+ preferenceManager.setMyServerApiKey(apiLayout.getEditText().getText().toString());
+ } else {
+ preferenceManager.setMyServerApiKey("");
+ }
+
+ if (myUser != null) {
+ preferenceManager.setMyUser(myUser);
+ }
+
+ if (myOrganisation != null) {
+ preferenceManager.setMyOrganisation(myOrganisation);
+ }
+
+ changesMade = false;
+ }
+
+ private void addSaveChangesListener() {
+ urlLayout.getEditText().addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ changesMade = true;
+ }
+ });
+
+ apiLayout.getEditText().addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ changesMade = true;
+ }
+ });
+ }
+
+ private void tryDownloadOrgInfo() {
+
+ if (myOrganisation != null) {
+
+ DialogInterface.OnClickListener pos = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ downloadOrgInfo();
+ }
+ };
+
+ new DialogFactory(this).createOverrideDialog(pos, null).show();
+
+ } else {
+
+ downloadOrgInfo();
+
+ }
+ }
+
+ private boolean validCredentials() {
+ boolean inputError = false;
+ String url = urlLayout.getEditText().getText().toString();
+ String auth = apiLayout.getEditText().getText().toString();
+
+ if (url.equals("")) {
+ urlLayout.setError("Required");
+ inputError = true;
+ }
+
+ if (auth.equals("")) {
+ apiLayout.setError("Required");
+ inputError = true;
+ }
+
+ if (inputError) {
+ return false;
+ }
+
+ urlLayout.setError(null);
+ apiLayout.setError(null);
+
+ return true;
+ }
+
+ private void downloadOrgInfo() {
+
+ if (!validCredentials()) {
+ return;
+ }
+
+ apiLayout.clearFocus();
+ urlLayout.clearFocus();
+
+ progressBar.setVisibility(View.VISIBLE);
+ emptyView.setVisibility(View.GONE);
+
+ final MispRequest mispRequest = MispRequest.Instance(this);
+ mispRequest.setServerCredentials(urlLayout.getEditText().getText().toString(), apiLayout.getEditText().getText().toString());
+
+ mispRequest.getMyUser(new MispRequest.UserCallback() {
+ @Override
+ public void onResult(JSONObject jsonUser) {
+ try {
+ myUser = new User(jsonUser);
+ } catch (JSONException e) {
+ makeSnackBar("Could not interpret user format");
+ return;
+ }
+
+ mispRequest.getOrganisation(myUser.getId(), new MispRequest.OrganisationCallback() {
+ @Override
+ public void onResult(JSONObject organisationInformation) {
+ try {
+ myOrganisation = new Organisation(organisationInformation);
+ changesMade = true;
+ } catch (JSONException e) {
+ makeSnackBar("Could not interpret organisation format");
+ return;
+ }
+
+ organisationView.setVisibility(View.VISIBLE);
+ emptyView.setVisibility(View.GONE);
+
+ progressBar.setVisibility(View.GONE);
+ visualizeOrganisation();
+ }
+
+ @Override
+ public void onError(VolleyError volleyError) {
+ makeSnackBar(ReadableError.toReadable(volleyError));
+ progressBar.setVisibility(View.GONE);
+ organisationView.setVisibility(View.GONE);
+ emptyView.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+
+ @Override
+ public void onError(VolleyError volleyError) {
+ makeSnackBar(ReadableError.toReadable(volleyError));
+ progressBar.setVisibility(View.GONE);
+ organisationView.setVisibility(View.GONE);
+ emptyView.setVisibility(View.VISIBLE);
+ }
+ });
+
+ }
+
+ private void visualizeOrganisation() {
+
+ TextView title = organisationView.findViewById(R.id.organisation_title);
+ title.setText(myOrganisation.getName());
+
+ TextView uuid = organisationView.findViewById(R.id.organisation_uuid);
+ uuid.setText(myOrganisation.getUuid());
+
+ TextView description = organisationView.findViewById(R.id.organisation_description);
+ description.setText(myOrganisation.getDescription());
+
+ TextView nationality = organisationView.findViewById(R.id.organisation_nationality);
+ nationality.setText(myOrganisation.getNationality());
+
+ TextView sector = findViewById(R.id.organisation_sector);
+ sector.setText(myOrganisation.getSector());
+
+ TextView users = findViewById(R.id.organisation_user_count);
+
+ users.setText("" + myOrganisation.getUserCount());
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+
+ switch (id) {
+ case R.id.fab_download_own_org_info:
+ tryDownloadOrgInfo();
+ break;
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_credentials, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+ int id = item.getItemId();
+
+ switch (id) {
+ case android.R.id.home:
+ exitSafely();
+ return true;
+
+// case R.id.menu_item_deleteData:
+// DialogInterface.OnClickListener pos = new DialogInterface.OnClickListener() {
+// @Override
+// public void onClick(DialogInterface dialog, int which) {
+// PreferenceManager.Instance(getApplicationContext()).clearCredentialPreferences();
+// urlLayout.getEditText().setText("");
+// apiLayout.getEditText().setText("");
+// myOrganisation = null;
+// myUser = null;
+// emptyView.setVisibility(View.VISIBLE);
+// organisationView.setVisibility(View.GONE);
+// }
+// };
+//
+// new DialogFactory(this).createDeleteDialog(pos, null).show();
+//
+// break;
+
+ case R.id.load_config:
+
+ // MOTOROLA
+ if (Build.VERSION.SDK_INT <= 25) {
+ urlLayout.getEditText().setText("http://192.168.178.200");
+ apiLayout.getEditText().setText("dcfgDrNy3SyASmo9WRqyJ4LhsN1xWJ7phfTjklFa");
+ } else {
+ urlLayout.getEditText().setText("http://192.168.178.201");
+ apiLayout.getEditText().setText("5BGhMzdHIWvaxyrTUUVNk2NflDPzXJRZQvOa3CE2");
+ }
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onBackPressed() {
+ exitSafely();
+ }
+
+ private void exitSafely() {
+
+ if (changesMade || !saveAuthkeyPrefSet) {
+ saveDialog(new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ savePreferences();
+ finish();
+ }
+ }, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+ } else {
+ finish();
+ }
+ }
+
+ private void makeSnackBar(String message) {
+ Snackbar.make(findViewById(R.id.coordinator), message, Snackbar.LENGTH_LONG).show();
+ }
+
+ private void saveDialog(DialogInterface.OnClickListener positive, DialogInterface.OnClickListener negative) {
+ AlertDialog.Builder adb = new AlertDialog.Builder(this);
+
+ adb.setTitle(getResources().getString(R.string.unsaved_changes));
+ adb.setMessage("\n" + getResources().getString(R.string.save_changes));
+
+ @SuppressLint("InflateParams")
+ View checkBoxView = getLayoutInflater().inflate(R.layout.dialog_save_authkey, null);
+ CheckBox c = checkBoxView.findViewById(R.id.checkbox);
+ c.setChecked(saveAuthkey);
+
+ c.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ saveAuthkey = isChecked;
+ }
+ });
+
+ adb.setView(checkBoxView);
+
+ adb.setPositiveButton(getResources().getString(R.string.save), positive);
+ adb.setNegativeButton(getResources().getString(R.string.discard), negative);
+
+ Dialog d = adb.create();
+ d.setCancelable(false);
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+ d.show();
+ }
+
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/MainActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/MainActivity.java
new file mode 100644
index 0000000..b788ee6
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/MainActivity.java
@@ -0,0 +1,185 @@
+package de.overview.wg.its.mispauth;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+import de.overview.wg.its.mispauth.adapter.SyncedPartnerAdapter;
+import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
+import de.overview.wg.its.mispauth.model.SyncedPartner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SuppressWarnings("ConstantConditions")
+public class MainActivity extends AppCompatActivity {
+
+ private List syncedPartnerList = new ArrayList<>();
+ private SyncedPartnerAdapter syncedPartnerAdapter;
+ private TextView emptyPartnerListView;
+ private RecyclerView syncedPartnerRecyclerView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ initializeViews();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+
+ // Make icon white (compat limitation in xml)
+ Drawable drawable = menu.findItem(R.id.menu_item_credential_settings).getIcon();
+ drawable = DrawableCompat.wrap(drawable);
+ DrawableCompat.setTint(drawable, ContextCompat.getColor(this, R.color.colorWhite));
+ menu.findItem(R.id.menu_item_credential_settings).setIcon(drawable);
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+
+ switch (id) {
+ case R.id.menu_item_credential_settings:
+ startActivity(new Intent(this, CredentialsActivity.class));
+ return true;
+
+ case R.id.menu_item_delete_local_data:
+ createSelectDeleteDialog();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void initializeViews() {
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+
+ FloatingActionButton fab = findViewById(R.id.fab);
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startSyncActivity();
+ }
+ });
+
+ emptyPartnerListView = findViewById(R.id.empty);
+ syncedPartnerRecyclerView = findViewById(R.id.recyclerView);
+
+ syncedPartnerAdapter = new SyncedPartnerAdapter(this, syncedPartnerList);
+ RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
+ syncedPartnerRecyclerView.setLayoutManager(mLayoutManager);
+ syncedPartnerRecyclerView.setItemAnimator(new DefaultItemAnimator());
+ syncedPartnerRecyclerView.setAdapter(syncedPartnerAdapter);
+
+ refreshSyncedPartnerList();
+ }
+
+ private void createSelectDeleteDialog() {
+
+ final PreferenceManager prefs = PreferenceManager.Instance(this);
+
+ AlertDialog.Builder adb = new AlertDialog.Builder(this);
+
+ adb.setTitle("Delete Local Data");
+ adb.setMessage("(Checked items will be deleted)");
+
+ @SuppressLint("InflateParams")
+ View checkBoxView = getLayoutInflater().inflate(R.layout.dialog_select_delete_data, null);
+
+ final CheckBox checkSyncedPartner = checkBoxView.findViewById(R.id.check_synced_partner_list);
+ final CheckBox checkCredentials = checkBoxView.findViewById(R.id.check_credentials);
+ final CheckBox checkUserData = checkBoxView.findViewById(R.id.check_user_preferences);
+
+ adb.setView(checkBoxView);
+
+ adb.setPositiveButton(getResources().getString(R.string.delete), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (checkSyncedPartner.isChecked()) {
+ prefs.clearSyncedInformationPreferences();
+ }
+
+ if (checkCredentials.isChecked()) {
+ prefs.clearCredentialPreferences();
+ }
+
+ if (checkUserData.isChecked()) {
+ prefs.clearUserPreferences();
+ }
+ }
+ });
+
+ adb.setNegativeButton(getResources().getString(android.R.string.cancel), null);
+
+ Dialog d = adb.create();
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+ d.show();
+ }
+
+ private void refreshSyncedPartnerList() {
+ syncedPartnerList = PreferenceManager.Instance(this).getSyncedPartnerList();
+
+ if (syncedPartnerList == null) {
+ emptyPartnerListView.setVisibility(View.VISIBLE);
+ syncedPartnerRecyclerView.setVisibility(View.GONE);
+ } else {
+ syncedPartnerAdapter.setSyncedPartnerList(syncedPartnerList);
+ }
+ }
+
+ private void startSyncActivity() {
+
+ PreferenceManager preferenceManager = PreferenceManager.Instance(this);
+
+ if (preferenceManager.getMyOrganisation() == null || preferenceManager.getMyUser() == null) {
+
+ AlertDialog.Builder adb = new AlertDialog.Builder(this);
+ adb.setTitle(getResources().getString(R.string.missing_local_information_title));
+ adb.setMessage(getResources().getString(R.string.missing_local_information_message));
+
+ adb.setPositiveButton(getResources().getString(R.string.enter_credentials), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ startCredentialsActivity();
+ }
+ });
+
+ adb.setNegativeButton(android.R.string.cancel, null);
+ adb.show();
+
+ } else {
+ Intent intent = new Intent(this, SyncActivity.class);
+ startActivity(intent);
+ }
+
+ }
+
+ private void startCredentialsActivity() {
+ startActivity(new Intent(this, CredentialsActivity.class));
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/SyncActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/SyncActivity.java
new file mode 100644
index 0000000..cf539f7
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/SyncActivity.java
@@ -0,0 +1,281 @@
+package de.overview.wg.its.mispauth;
+
+import android.animation.Animator;
+import android.content.Intent;
+import android.graphics.Point;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.WindowManager;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.*;
+import com.google.gson.Gson;
+import de.overview.wg.its.mispauth.auxiliary.AESSecurity;
+import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
+import de.overview.wg.its.mispauth.auxiliary.RandomString;
+import de.overview.wg.its.mispauth.auxiliary.TempAuth;
+import de.overview.wg.its.mispauth.cam.CameraFragment;
+import de.overview.wg.its.mispauth.model.*;
+import net.glxn.qrgen.android.QRCode;
+
+public class SyncActivity extends AppCompatActivity implements View.OnClickListener {
+
+ private static final String SCAN_PUB_KEY_FRAG_TAG = "scan_public_key_fragment_tag";
+ private static final String SCAN_INFO_FRAG_TAG = "scan_info_fragment_tag";
+
+ private AESSecurity aesSecurity;
+
+ private Fragment currentFragment;
+ private String currentFragmentTag;
+
+ // Views for QR code
+ private LinearLayout qrBackground;
+ private ImageView qrImageView;
+ private Button forwardButton;
+ private TextView forwardDescription;
+
+ private SyncInformationQr partnerInformation;
+
+ private FragmentManager manager;
+ private FragmentTransaction transaction;
+ private PreferenceManager preferenceManager;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ setContentView(R.layout.activity_public_key_exchange);
+
+ manager = getSupportFragmentManager();
+ preferenceManager = PreferenceManager.Instance(this);
+
+ initializeViews();
+
+ aesSecurity = AESSecurity.getInstance();
+
+ setScanTypeFragment(0);
+ }
+
+ private void initializeViews() {
+
+ ImageButton closeButton = findViewById(R.id.close);
+ forwardButton = findViewById(R.id.forward);
+
+ closeButton.setOnClickListener(this);
+
+ forwardButton.setOnClickListener(this);
+ forwardButton.setEnabled(false);
+ forwardDescription = findViewById(R.id.forward_description);
+
+ qrImageView = findViewById(R.id.qr_imageView);
+ qrBackground = findViewById(R.id.qr_background);
+
+ setContinueScreenEnabled(false);
+ }
+
+ private void setScanTypeFragment(int mode) {
+
+ transaction = manager.beginTransaction();
+
+ User myUser = preferenceManager.getMyUser();
+ Organisation myOrg = preferenceManager.getMyOrganisation();
+
+ switch (mode) {
+
+ case 0:
+
+ setContinueScreenEnabled(false);
+
+ PublicKeyQr pkqr = new PublicKeyQr(myOrg.getName(),
+ myUser.getEmail(),
+ AESSecurity.publicKeyToString(aesSecurity.getPublicKey()));
+
+ setQrContent(pkqr.toJSON().toString(), 0.6f);
+
+ currentFragment = CameraFragment.newInstance(CameraFragment.ScanMode.PUBLIC_KEY);
+ currentFragmentTag = SCAN_PUB_KEY_FRAG_TAG;
+
+ break;
+
+ case 1:
+
+ setContinueScreenEnabled(false);
+
+ TempAuth.TMP_AUTH_KEY = new RandomString(40).nextString();
+
+ Server serverForMeOnOtherInstance = new Server();
+ serverForMeOnOtherInstance.setAuthkey(TempAuth.TMP_AUTH_KEY);
+ serverForMeOnOtherInstance.setName("SyncServer for " + myOrg.getName());
+ serverForMeOnOtherInstance.setUrl(preferenceManager.getMyServerUrl());
+
+ SyncInformationQr siqr = new SyncInformationQr(
+ preferenceManager.getMyOrganisation(),
+ serverForMeOnOtherInstance,
+ preferenceManager.getMyUser());
+
+ setQrContent(aesSecurity.encrypt(siqr.toJSON().toString()), 0.9f);
+
+ currentFragment = CameraFragment.newInstance(CameraFragment.ScanMode.INFO);
+ currentFragmentTag = SCAN_INFO_FRAG_TAG;
+
+ break;
+
+ default:
+
+ transaction.remove(currentFragment);
+ transaction.commit();
+
+ currentFragment = null;
+
+ finish();
+
+ return;
+ }
+
+ transaction.replace(R.id.fragment_container, currentFragment, currentFragmentTag);
+ transaction.commit();
+ }
+
+ private void setQrContent(String content, float qrToScreenRatio) {
+
+ Display display = getWindowManager().getDefaultDisplay();
+ Point size = new Point();
+ display.getSize(size);
+
+ int width = (int) (size.x * qrToScreenRatio);
+
+ //noinspection SuspiciousNameCombination
+ qrImageView.setImageBitmap(QRCode.from(content)
+ .withColor(0xFF000000, 0x00FFFFFF)
+ .withSize(width, width)
+ .bitmap());
+
+ circularReveal(qrBackground, true, 400);
+ }
+
+ @Override
+ public void onClick(View v) {
+
+ switch (v.getId()) {
+
+ case R.id.close:
+ finish();
+ break;
+
+ case R.id.forward:
+
+ if (currentFragmentTag.equals(SCAN_PUB_KEY_FRAG_TAG)) {
+ setScanTypeFragment(1);
+ } else if (currentFragmentTag.equals(SCAN_INFO_FRAG_TAG)) {
+ startUploadActivity();
+ }
+
+ break;
+
+ }
+ }
+
+ private void setContinueScreenEnabled(boolean enabled) {
+ if (enabled) {
+ forwardButton.setVisibility(View.VISIBLE);
+ forwardDescription.setVisibility(View.VISIBLE);
+ } else {
+ forwardButton.setVisibility(View.INVISIBLE);
+ forwardDescription.setVisibility(View.INVISIBLE);
+ }
+
+ forwardButton.setEnabled(enabled);
+ }
+
+ public void onPublicKeyResult(PublicKeyQr pkqr) {
+ aesSecurity.setForeignPublicKey(AESSecurity.publicKeyFromString(pkqr.getKey()));
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setContinueScreenEnabled(true);
+ }
+ });
+ }
+
+ public void onSyncInfoResult(SyncInformationQr siqr) {
+ partnerInformation = siqr;
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ setContinueScreenEnabled(true);
+ }
+ });
+ }
+
+ private void startUploadActivity() {
+
+ Intent i = new Intent(this, UploadActivity.class);
+ String partnerString = new Gson().toJson(partnerInformation);
+ i.putExtra(UploadActivity.PARTNER_INFO_BUNDLE_KEY, partnerString);
+
+ startActivity(i);
+ finish();
+
+ }
+
+ private void circularReveal(final View v, final boolean open, final long duration) {
+
+ v.post(new Runnable() {
+ @Override
+ public void run() {
+ int cx = v.getWidth() / 2;
+ int cy = v.getHeight() / 2;
+
+ float finalRadius = (float) Math.hypot(cx, cy);
+
+ Animator anim;
+
+
+ if (open) {
+ anim = ViewAnimationUtils.createCircularReveal(v, cx, cy, 0, finalRadius);
+ v.setVisibility(View.VISIBLE);
+ } else {
+ anim = ViewAnimationUtils.createCircularReveal(v, cx, cy, finalRadius, 0);
+ }
+
+ anim.setInterpolator(new DecelerateInterpolator());
+
+ anim.setDuration(duration);
+ anim.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!open) {
+ v.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ });
+ anim.start();
+ }
+ });
+
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/UploadActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/UploadActivity.java
new file mode 100644
index 0000000..3219388
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/UploadActivity.java
@@ -0,0 +1,240 @@
+package de.overview.wg.its.mispauth;
+
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import com.android.volley.VolleyError;
+import com.google.gson.Gson;
+import de.overview.wg.its.mispauth.adapter.UploadStateAdapter;
+import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
+import de.overview.wg.its.mispauth.auxiliary.ReadableError;
+import de.overview.wg.its.mispauth.auxiliary.TempAuth;
+import de.overview.wg.its.mispauth.model.*;
+import de.overview.wg.its.mispauth.network.MispRequest;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SuppressWarnings("ConstantConditions")
+public class UploadActivity extends AppCompatActivity implements View.OnClickListener {
+
+ static final String PARTNER_INFO_BUNDLE_KEY = "partner_info";
+
+ private MispRequest mispRequest;
+ private SyncInformationQr partnerInformation;
+
+ private Organisation partnerOrganisation;
+ private User partnerSyncUser;
+ private Server partnerServer;
+
+ private UploadStateAdapter uploadStateAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_upload);
+
+ Bundle b = getIntent().getExtras();
+ assert b != null;
+ String info = b.getString(PARTNER_INFO_BUNDLE_KEY);
+
+ partnerInformation = new Gson().fromJson(info, SyncInformationQr.class);
+
+ mispRequest = MispRequest.Instance(this);
+
+ initializeViews();
+
+ SyncUpload();
+ }
+
+ private void initializeViews() {
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ getSupportActionBar().setDisplayShowHomeEnabled(false);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(false);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+
+ FloatingActionButton fab = findViewById(R.id.fab);
+ fab.setOnClickListener(this);
+
+ RecyclerView recyclerView = findViewById(R.id.recyclerView);
+ uploadStateAdapter = new UploadStateAdapter();
+ RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
+ recyclerView.setLayoutManager(mLayoutManager);
+ recyclerView.setItemAnimator(new DefaultItemAnimator());
+ recyclerView.setAdapter(uploadStateAdapter);
+ }
+
+ @Override
+ public void onClick(View v) {
+
+ int id = v.getId();
+
+ switch (id) {
+ case R.id.fab:
+ finish();
+ break;
+ }
+ }
+
+ private void setCurrentStateWrapper(int stateNumber, UploadState.State state) {
+ syncUploadStates.get(stateNumber).setCurrentState(state);
+ uploadStateAdapter.notifyItemChanged(stateNumber);
+ }
+
+ private List syncUploadStates = new ArrayList<>();
+
+ private void SyncUpload() {
+
+ partnerOrganisation = partnerInformation.getOrganisation();
+ partnerSyncUser = partnerInformation.getUser();
+ partnerServer = partnerInformation.getServer();
+
+ syncUploadStates.add(new UploadState("Add local organisation"));
+ syncUploadStates.add(new UploadState("Add sync user to organisation"));
+ syncUploadStates.add(new UploadState("Add external organisation"));
+ syncUploadStates.add(new UploadState("Add sync server"));
+
+ uploadStateAdapter.setStateList(syncUploadStates);
+
+ uploadSyncOrganisation();
+ }
+
+ private void uploadSyncOrganisation() {
+ setCurrentStateWrapper(0, UploadState.State.IN_PROGRESS);
+// syncUploadStates.get(0).setCurrentState(UploadState.State.IN_PROGRESS);
+ mispRequest.addOrganisation(partnerOrganisation, new MispRequest.OrganisationCallback() {
+ @Override
+ public void onResult(JSONObject organisationInformation) {
+ try {
+
+ Organisation retOrg = new Organisation(organisationInformation);
+ setCurrentStateWrapper(0, UploadState.State.DONE);
+// syncUploadStates.get(0).setCurrentState(UploadState.State.DONE);
+ uploadSyncUser(retOrg.getId());
+
+ } catch (JSONException e) {
+ syncUploadStates.get(0).setError("Could not read server response");
+ setCurrentStateWrapper(0, UploadState.State.ERROR);
+// syncUploadStates.get(0).setCurrentState(UploadState.State.ERROR);
+ e.printStackTrace();
+ }
+
+ }
+
+ @Override
+ public void onError(VolleyError volleyError) {
+ syncUploadStates.get(0).setError(ReadableError.toReadable(volleyError));
+ setCurrentStateWrapper(0, UploadState.State.ERROR);
+// syncUploadStates.get(0).setCurrentState(UploadState.State.ERROR);
+ }
+ });
+ }
+
+ private void uploadSyncUser(int orgID) {
+
+ setCurrentStateWrapper(1, UploadState.State.IN_PROGRESS);
+// syncUploadStates.get(1).setCurrentState(UploadState.State.IN_PROGRESS);
+
+ partnerSyncUser.setOrgId(orgID);
+ partnerSyncUser.setAuthkey(TempAuth.TMP_AUTH_KEY);
+ partnerSyncUser.setRoleId(User.RoleId.SYNC_USER);
+
+ mispRequest.addUser(partnerSyncUser, new MispRequest.UserCallback() {
+ @Override
+ public void onResult(JSONObject myUserInformation) {
+ setCurrentStateWrapper(1, UploadState.State.DONE);
+// syncUploadStates.get(1).setCurrentState(UploadState.State.DONE);
+ uploadExternalSyncOrganisation();
+ }
+
+ @Override
+ public void onError(VolleyError volleyError) {
+ syncUploadStates.get(1).setError(ReadableError.toReadable(volleyError));
+ setCurrentStateWrapper(1, UploadState.State.ERROR);
+// syncUploadStates.get(1).setCurrentState(UploadState.State.ERROR);
+ }
+ });
+ }
+
+ private void uploadExternalSyncOrganisation() {
+
+ setCurrentStateWrapper(2, UploadState.State.IN_PROGRESS);
+
+ partnerOrganisation.setName(partnerOrganisation.getName() + " (Remote)");
+ partnerOrganisation.setLocal(false);
+
+ mispRequest.addOrganisation(partnerOrganisation, new MispRequest.OrganisationCallback() {
+ @Override
+ public void onResult(JSONObject organisationInformation) {
+ try {
+
+ Organisation extOrg = new Organisation(organisationInformation);
+ setCurrentStateWrapper(2, UploadState.State.DONE);
+ uploadSyncServer(extOrg.getId());
+
+ } catch (JSONException e) {
+ syncUploadStates.get(2).setError("Could not read server response");
+ setCurrentStateWrapper(2, UploadState.State.ERROR);
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(VolleyError volleyError) {
+ syncUploadStates.get(2).setError(ReadableError.toReadable(volleyError));
+ setCurrentStateWrapper(2, UploadState.State.ERROR);
+ }
+ });
+ }
+
+ private void uploadSyncServer(int remoteOrgId) {
+
+ setCurrentStateWrapper(3, UploadState.State.IN_PROGRESS);
+
+ partnerServer.setRemoteOrgId(remoteOrgId);
+ partnerServer.setPush(true);
+
+ mispRequest.addServer(partnerServer, new MispRequest.ServerCallback() {
+ @Override
+ public void onResult(JSONObject servers) {
+ setCurrentStateWrapper(3, UploadState.State.DONE);
+ updateSyncedOrganisationList();
+ }
+
+ @Override
+ public void onError(VolleyError volleyError) {
+ syncUploadStates.get(3).setError(ReadableError.toReadable(volleyError));
+ setCurrentStateWrapper(3, UploadState.State.ERROR);
+ }
+ });
+ }
+
+ private void updateSyncedOrganisationList() {
+
+ PreferenceManager preferenceManager = PreferenceManager.Instance(this);
+
+ List syncedPartnerList = preferenceManager.getSyncedPartnerList();
+
+ if (syncedPartnerList == null) {
+ syncedPartnerList = new ArrayList<>();
+ }
+
+ SyncedPartner sp = new SyncedPartner(
+ partnerInformation.getOrganisation().getName(),
+ partnerInformation.getServer().getUrl());
+
+ sp.generateTimeStamp();
+ syncedPartnerList.add(sp);
+ preferenceManager.setSyncedPartnerList(syncedPartnerList);
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/activity/MainActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/activity/MainActivity.java
deleted file mode 100644
index 2ec5c12..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/activity/MainActivity.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package de.overview.wg.its.mispauth.activity;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.design.widget.FloatingActionButton;
-import android.support.v4.widget.SwipeRefreshLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.DividerItemDecoration;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.Toast;
-import com.android.volley.VolleyError;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.adapter.ExtOrgAdapter;
-import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
-import de.overview.wg.its.mispauth.auxiliary.ReadableError;
-import de.overview.wg.its.mispauth.model.Organisation;
-import de.overview.wg.its.mispauth.network.MispRequest;
-import org.json.JSONObject;
-
-public class MainActivity extends AppCompatActivity {
-
- private Organisation[] externalOrganisations;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- getExternalOrganisations();
- setUpRecyclerView();
-
- FloatingActionButton fabAdd = findViewById(R.id.fab_add);
- final FloatingActionButton fabSync = findViewById(R.id.fab_sync);
-
- fabAdd.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (fabSync.getVisibility() == View.GONE) {
- fabSync.setVisibility(View.VISIBLE);
- } else {
- fabSync.setVisibility(View.GONE);
- }
- }
- });
-
- fabSync.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startSyncActivity();
- }
- });
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
-
- if (id == R.id.menu_item_settings) {
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- private void setUpRecyclerView() {
- RecyclerView orgRecyclerView = findViewById(R.id.orgRecyclerView);
- orgRecyclerView.setHasFixedSize(true);
-
- RecyclerView.LayoutManager orgLayoutManager = new LinearLayoutManager(this);
- orgRecyclerView.setLayoutManager(orgLayoutManager);
-
- DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(orgRecyclerView.getContext(), 1);
- orgRecyclerView.addItemDecoration(dividerItemDecoration);
-
- RecyclerView.Adapter orgAdapter = new ExtOrgAdapter(this, externalOrganisations);
- orgRecyclerView.setAdapter(orgAdapter);
-
- if (externalOrganisations.length == 0) {
- orgRecyclerView.setVisibility(View.GONE);
- findViewById(R.id.empty_view).setVisibility(View.VISIBLE);
- } else {
- orgRecyclerView.setVisibility(View.VISIBLE);
- findViewById(R.id.empty_view).setVisibility(View.GONE);
- }
-
- final SwipeRefreshLayout refreshLayout = findViewById(R.id.recycler_refresh);
- refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
- @Override
- public void onRefresh() {
- // TODO do stuff
- // refreshLayout.setRefreshing(false);
- }
- });
- }
-
- private void getExternalOrganisations() {
- Organisation a = new Organisation();
- a.setName("Ferrari");
- a.setDescription("Ferrari has nothing to share");
- a.setSector("Fast cars");
- a.setNationality("Italy");
- a.setLocal(true);
-
- externalOrganisations = new Organisation[]{a};
- }
-
- private void startSyncActivity() {
- startActivity(new Intent(this, SyncActivity.class));
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/activity/SettingsActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/activity/SettingsActivity.java
deleted file mode 100644
index 658f90f..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/activity/SettingsActivity.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package de.overview.wg.its.mispauth.activity;
-
-import android.os.Bundle;
-import android.support.design.widget.Snackbar;
-import android.support.design.widget.TextInputLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import com.android.volley.VolleyError;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
-import de.overview.wg.its.mispauth.auxiliary.ReadableError;
-import de.overview.wg.its.mispauth.model.Organisation;
-import de.overview.wg.its.mispauth.model.User;
-import de.overview.wg.its.mispauth.network.MispRequest;
-import org.json.JSONObject;
-
-public class SettingsActivity extends AppCompatActivity {
-
- private static final String TAG = "DEBUG";
-
- private PreferenceManager preferenceManager;
- private ProgressBar progressBar;
- private TextInputLayout serverUrlLayout, apiKeyLayout;
- private EditText serverUrlText, apiKeyText;
-
- private Organisation org;
- private User user;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_settings);
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- getSupportActionBar().setDisplayShowHomeEnabled(true);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- serverUrlLayout = findViewById(R.id.input_layout_server_url);
- apiKeyLayout = findViewById(R.id.input_layout_api_key);
- serverUrlText = findViewById(R.id.edit_server_url);
- apiKeyText = findViewById(R.id.edit_api_key);
- progressBar = findViewById(R.id.progressBar);
-
- findViewById(R.id.fab_download_own_org_info).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- downloadMyOrgInfo();
- }
- });
-
- apiKeyText.setOnKeyListener(new View.OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (keyCode == 66) {
- hideKeyboard(v);
- apiKeyText.clearFocus();
- return true;
- }
- return false;
- }
- });
-
- restoreSavedValues();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_settings, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
-
- if (id == R.id.menu_item_deleteData) {
- serverUrlText.setText("");
- apiKeyText.setText("");
- preferenceManager.deleteAllLocalData();
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- private void setOrganisation(Organisation org) {
-
- if(org == null) {
- return;
- }
-
- TextView title = findViewById(R.id.organisation_title);
- TextView uuid = findViewById(R.id.organisation_uuid);
- TextView description = findViewById(R.id.organisation_description);
- TextView nationality = findViewById(R.id.organisation_nationality);
- TextView sector = findViewById(R.id.organisation_sector);
- TextView userCount = findViewById(R.id.organisation_user_count);
-
- title.setText(org.getName());
- uuid.setText(org.getUuid());
- description.setText(org.getDescription());
- nationality.setText(org.getNationality());
- sector.setText(org.getSector());
- userCount.setText("" + org.getUserCount());
- }
-
- private void restoreSavedValues() {
- preferenceManager = PreferenceManager.Instance(this);
-
- serverUrlText.setText(preferenceManager.getMyServerUrl());
- apiKeyText.setText(preferenceManager.getMyServerApiKey());
-
- setOrganisation(preferenceManager.getMyOrganisation());
- }
-
- private void downloadMyOrgInfo(){
- user = new User();
- org = new Organisation();
-
- boolean failed = false;
-
- String tmpServerUrl = serverUrlText.getText().toString();
- String tmpApiKey = apiKeyText.getText().toString();
-
- if(tmpServerUrl.isEmpty()) {
- serverUrlLayout.setError("Server URL is required");
- failed = true;
- }
-
- if(tmpApiKey.isEmpty()) {
- apiKeyLayout.setError("API Key is required");
- failed = true;
- }
-
- if(failed) {
- return;
- } else {
- serverUrlLayout.setError(null);
- apiKeyLayout.setError(null);
- }
-
- final MispRequest request = MispRequest.Instance(this);
- request.setServerCredentials(tmpServerUrl, tmpApiKey);
-
- progressBar.setVisibility(View.VISIBLE);
-
- request.myUserInformation(new MispRequest.UserCallback() {
-
- @Override
- public void onResult(JSONObject myUserInformation) {
-
- user.fromJSON(myUserInformation);
- preferenceManager.setMyUser(user);
-
- int orgID = user.getOrgId();
-
- request.getOrganisation(orgID, new MispRequest.OrganisationCallback() {
-
- @Override
- public void onResult(JSONObject organisationInformation) {
- progressBar.setVisibility(View.GONE);
-
- org.fromJSON(organisationInformation);
-
- preferenceManager.setMyOrganisation(org);
-
- setOrganisation(org);
- }
-
- @Override
- public void onError(VolleyError volleyError) {
- progressBar.setVisibility(View.GONE);
- MakeSnackbar(ReadableError.toReadable(volleyError));
- Log.e(TAG, "onError: " + volleyError.toString());
- }
- });
- }
-
- @Override
- public void onError(VolleyError volleyError) {
- progressBar.setVisibility(View.GONE);
- MakeSnackbar(ReadableError.toReadable(volleyError));
- }
- });
-
- // If auth was successful: save new credentials
- preferenceManager.setMyServerUrl(tmpServerUrl);
- preferenceManager.setMyServerApiKey(tmpApiKey);
- }
-
- private void MakeSnackbar(String msg){
- View contextView = findViewById(R.id.coordinator);
- Snackbar.make(contextView, msg, Snackbar.LENGTH_LONG).show();
- }
-
- private void hideKeyboard(View view) {
- InputMethodManager manager = (InputMethodManager) view.getContext().getSystemService(INPUT_METHOD_SERVICE);
- if (manager != null) {
- manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
- }
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/activity/SyncActivity.java b/app/src/main/java/de/overview/wg/its/mispauth/activity/SyncActivity.java
deleted file mode 100644
index 0daec67..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/activity/SyncActivity.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package de.overview.wg.its.mispauth.activity;
-
-import android.os.Bundle;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.View;
-import android.widget.Button;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
-import de.overview.wg.its.mispauth.fragment.*;
-
-public class SyncActivity extends AppCompatActivity {
-
- private static final String TAG = "DEBUG";
-
- private PreferenceManager preferenceManager;
-
- private Button prevButton, nextButton;
- private int partnerChoice = -1;
-
- private int currentFragmentPosition = 0;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_sync);
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- preferenceManager = PreferenceManager.Instance(this);
-
- nextButton = findViewById(R.id.nextButton);
- prevButton = findViewById(R.id.backButton);
-
- nextButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getFragment(currentFragmentPosition + 1, true);
- }
- });
- prevButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getFragment(currentFragmentPosition - 1, true);
- }
- });
-
- getFragment(0, false);
- }
-
- private void getNextFragment() {
- getFragment(currentFragmentPosition + 1, true);
- }
-
- private void getFragment(int position, boolean animate) {
-
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-
- if (animate) {
- if (position > currentFragmentPosition) {
- transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
- } else {
- transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
- }
- }
-
- currentFragmentPosition = position;
-
- switch (position) {
-
- case 0:
- prevButton.setEnabled(false);
- nextButton.setEnabled(false);
-
- prevButton.setText(R.string.back);
- nextButton.setText(R.string.next);
-
- transaction.replace(R.id.fragmentContainer, new SyncStartFragment());
- break;
-
- case 1:
- prevButton.setEnabled(true);
-
- prevButton.setText(R.string.back);
- nextButton.setText(R.string.next);
-
- if (partnerChoice == 1) {
-
- nextButton.setEnabled(false);
- transaction.replace(R.id.fragmentContainer, new ScanQrFragment(), "FRAGMENT_SCAN");
-
- } else {
-
- nextButton.setEnabled(true);
- transaction.replace(R.id.fragmentContainer, new ShowQrFragment(), "FRAGMENT_SHOW");
-
- }
- break;
-
- case 2:
- if (partnerChoice == 1) {
-
- prevButton.setEnabled(true);
- nextButton.setEnabled(true);
-
- prevButton.setText(R.string.reject);
- nextButton.setText(R.string.accept);
-
- transaction.replace(R.id.fragmentContainer, new ReviewQrFragment());
-
- } else {
-
- prevButton.setEnabled(true);
- nextButton.setEnabled(false);
-
- prevButton.setText(R.string.back);
- nextButton.setText(R.string.next);
-
- transaction.replace(R.id.fragmentContainer, new ScanQrFragment(), "FRAGMENT_SCAN");
- }
- break;
-
- case 3:
-
- if (partnerChoice == 1) {
- prevButton.setEnabled(true);
- nextButton.setEnabled(true);
-
- prevButton.setText(R.string.back);
- nextButton.setText(R.string.next);
-
- transaction.replace(R.id.fragmentContainer, new ShowQrFragment(), "FRAGMENT_SHOW");
- } else {
- prevButton.setEnabled(true);
- nextButton.setEnabled(true);
-
- prevButton.setText(R.string.reject);
- nextButton.setText(R.string.accept);
-
- transaction.replace(R.id.fragmentContainer, new ReviewQrFragment());
- }
- break;
-
- case 4:
-
- nextButton.setText(R.string.done);
- nextButton.setEnabled(true);
-
- nextButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- finish();
- }
- });
-
- transaction.replace(R.id.fragmentContainer, new UploadFragment());
-
- break;
- }
-
- transaction.commit();
- }
-
- public void setPartnerChoice(int choice) {
-
- partnerChoice = choice;
-
- if (choice != -1) {
- nextButton.setEnabled(true);
- } else {
- nextButton.setEnabled(false);
- }
- }
-
- public void setScannedQr(String qr) {
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (partnerChoice == 1) {
- getFragment(2, true);
- } else {
- getFragment(3, true);
- }
- }
- });
-
-// try {
-// OrganisationDialog d = new OrganisationDialog(this);
-// Organisation o = new Organisation();
-// o.fromJSON(new JSONObject(qr));
-// d.createAcceptDialog(o, new OrganisationDialog.DialogCallback() {
-// @Override
-// public void onAccept() {
-// nextButton.setEnabled(true);
-// }
-//
-// @Override
-// public void onReject() {
-// scanFragment.setReadQr(true);
-// scanFragment.openCamera();
-// }
-// });
-//
-// } catch (JSONException e) {
-// e.printStackTrace();
-// }
-
- }
-
- public void uploadReady() {
- nextButton.setEnabled(true);
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/adapter/ExtOrgAdapter.java b/app/src/main/java/de/overview/wg/its/mispauth/adapter/ExtOrgAdapter.java
deleted file mode 100644
index 50ffb71..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/adapter/ExtOrgAdapter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package de.overview.wg.its.mispauth.adapter;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.auxiliary.OrganisationDialog;
-import de.overview.wg.its.mispauth.model.Organisation;
-
-public class ExtOrgAdapter extends RecyclerView.Adapter {
-
- private Context context;
- private Organisation[] dataSet;
-
- public ExtOrgAdapter(Context context, Organisation[] dataSet) {
- this.context = context;
- this.dataSet = dataSet;
- }
-
- @NonNull
- @Override
- public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View extOrgView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_holder_ext_org, parent, false);
- return new ViewHolder(extOrgView);
- }
-
- @Override
- public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
- holder.orgTitle.setText(dataSet[position].getName());
- holder.subTitle.setText(dataSet[position].getDescription());
-
- holder.parentLayout.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- OrganisationDialog d = new OrganisationDialog(context);
- d.createInfoDialog(dataSet[position]);
- }
- });
- }
-
- @Override
- public int getItemCount() {
- return dataSet.length;
- }
-
- public static class ViewHolder extends RecyclerView.ViewHolder{
-
- RelativeLayout parentLayout;
- TextView orgTitle;
- TextView subTitle;
-
- public ViewHolder(View v) {
- super(v);
- parentLayout = v.findViewById(R.id.parent_layout);
- orgTitle = v.findViewById(R.id.ext_org_title);
- subTitle = v.findViewById(R.id.ext_org_sub_title);
- }
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/adapter/SyncedPartnerAdapter.java b/app/src/main/java/de/overview/wg/its/mispauth/adapter/SyncedPartnerAdapter.java
new file mode 100644
index 0000000..b62e7ee
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/adapter/SyncedPartnerAdapter.java
@@ -0,0 +1,58 @@
+package de.overview.wg.its.mispauth.adapter;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import de.overview.wg.its.mispauth.R;
+import de.overview.wg.its.mispauth.model.SyncedPartner;
+
+import java.util.List;
+
+public class SyncedPartnerAdapter extends RecyclerView.Adapter {
+
+ private List syncedPartnerList;
+
+ public class MyViewHolder extends RecyclerView.ViewHolder {
+ public TextView title, dateAdded, url;
+ public MyViewHolder(View view) {
+ super(view);
+ title = view.findViewById(R.id.title);
+ dateAdded = view.findViewById(R.id.dateSynced);
+ url = view.findViewById(R.id.url);
+ }
+ }
+
+ public SyncedPartnerAdapter(Context context, List syncedPartnerList) {
+ this.syncedPartnerList = syncedPartnerList;
+ }
+
+ public void setSyncedPartnerList(List syncedPartnerList) {
+ this.syncedPartnerList = syncedPartnerList;
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_synced_organisation, parent, false);
+ return new MyViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
+ SyncedPartner syncedPartner = syncedPartnerList.get(position);
+
+ holder.title.setText(syncedPartner.getName());
+ holder.url.setText(syncedPartner.getUrl());
+ holder.dateAdded.setText(syncedPartner.getSyncDate());
+ }
+
+ @Override
+ public int getItemCount() {
+ return syncedPartnerList.size();
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/adapter/UploadStateAdapter.java b/app/src/main/java/de/overview/wg/its/mispauth/adapter/UploadStateAdapter.java
new file mode 100644
index 0000000..4d3d9ce
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/adapter/UploadStateAdapter.java
@@ -0,0 +1,93 @@
+package de.overview.wg.its.mispauth.adapter;
+
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import de.overview.wg.its.mispauth.R;
+import de.overview.wg.its.mispauth.model.UploadState;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class UploadStateAdapter extends RecyclerView.Adapter {
+
+ private List stateList = new ArrayList<>();
+
+ class MyViewHolder extends RecyclerView.ViewHolder {
+
+ private TextView title, error;
+ private ImageView pendingIcon, errorIcon, doneIcon, inProgressIcon;
+
+ private MyViewHolder(View view) {
+
+ super(view);
+
+ title = view.findViewById(R.id.title);
+ error = view.findViewById(R.id.state_error_text);
+
+ pendingIcon = view.findViewById(R.id.state_pending);
+ errorIcon = view.findViewById(R.id.state_error);
+ doneIcon = view.findViewById(R.id.state_done);
+ inProgressIcon = view.findViewById(R.id.state_in_progress);
+ }
+
+ private void setState(UploadState.State state) {
+
+ error.setVisibility(View.GONE);
+ errorIcon.setVisibility(View.GONE);
+ pendingIcon.setVisibility(View.GONE);
+ doneIcon.setVisibility(View.GONE);
+ inProgressIcon.setVisibility(View.GONE);
+
+ switch (state) {
+ case PENDING:
+ pendingIcon.setVisibility(View.VISIBLE);
+ break;
+
+ case IN_PROGRESS:
+ inProgressIcon.setVisibility(View.VISIBLE);
+ break;
+
+ case DONE:
+ doneIcon.setVisibility(View.VISIBLE);
+ break;
+
+ case ERROR:
+ errorIcon.setVisibility(View.VISIBLE);
+ error.setVisibility(View.VISIBLE);
+ break;
+ }
+ }
+ }
+
+ public void setStateList(List stateList) {
+ this.stateList = stateList;
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public UploadStateAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_upload_state, parent, false);
+ return new UploadStateAdapter.MyViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull UploadStateAdapter.MyViewHolder holder, int position) {
+ UploadState state = stateList.get(position);
+
+ holder.title.setText(state.getTitle());
+ holder.error.setText(state.getError());
+ holder.setState(stateList.get(position).getCurrentState());
+ }
+
+ @Override
+ public int getItemCount() {
+ return stateList.size();
+ }
+
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/AESSecurity.java b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/AESSecurity.java
new file mode 100644
index 0000000..e116bc1
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/AESSecurity.java
@@ -0,0 +1,119 @@
+package de.overview.wg.its.mispauth.auxiliary;
+
+import android.util.Base64;
+
+import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+public class AESSecurity {
+
+ private static final String TAG = "MISP_LOGGING";
+ private static final String ALGORITHM = "AES";
+
+ private static AESSecurity instance;
+
+ private PublicKey publickey;
+ private KeyAgreement keyAgreement;
+ private byte[] sharedSecret;
+
+ private AESSecurity() {
+ initialize();
+ }
+
+ private void initialize() {
+ KeyPairGenerator kpg = null;
+
+ try {
+ kpg = KeyPairGenerator.getInstance("EC");
+ kpg.initialize(256);
+
+ KeyPair kp = kpg.generateKeyPair();
+
+ publickey = kp.getPublic();
+
+ keyAgreement = KeyAgreement.getInstance("ECDH");
+ keyAgreement.init(kp.getPrivate());
+
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setForeignPublicKey(PublicKey publickey) {
+ try {
+ keyAgreement.doPhase(publickey, true);
+ sharedSecret = keyAgreement.generateSecret();
+ } catch (InvalidKeyException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public String encrypt(String data) {
+ try {
+ Key key = generateKey();
+ Cipher c = Cipher.getInstance(ALGORITHM);
+ c.init(Cipher.ENCRYPT_MODE, key);
+
+ byte[] encVal = c.doFinal(data.getBytes());
+
+ return Base64.encodeToString(encVal, 0);
+
+ } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return data;
+ }
+
+ public String decrypt(String data) {
+ try {
+ Key key = generateKey();
+ Cipher c = Cipher.getInstance(ALGORITHM);
+ c.init(Cipher.DECRYPT_MODE, key);
+
+ byte[] decoded = Base64.decode(data, 0);
+ byte[] decValue = c.doFinal(decoded);
+ return new String(decValue);
+ } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return data;
+ }
+
+ public PublicKey getPublicKey() {
+ return publickey;
+ }
+
+ private Key generateKey() {
+ return new SecretKeySpec(sharedSecret, ALGORITHM);
+ }
+
+ public static String publicKeyToString(PublicKey key) {
+ return Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
+ }
+ public static PublicKey publicKeyFromString(String key) {
+
+ KeyFactory kf = null;
+
+ byte[] input = Base64.decode(key, Base64.DEFAULT);
+
+ try {
+ kf = KeyFactory.getInstance("EC"); // normal: DH
+ return kf.generatePublic(new X509EncodedKeySpec(input));
+ } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public static AESSecurity getInstance() {
+ if(instance == null) {
+ instance = new AESSecurity();
+ }
+
+ return instance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/OrganisationDialog.java b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/OrganisationDialog.java
deleted file mode 100644
index 42b2abd..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/OrganisationDialog.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package de.overview.wg.its.mispauth.auxiliary;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.support.v7.app.AlertDialog;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.model.Organisation;
-
-public class OrganisationDialog {
-
- private AlertDialog.Builder dialogBuilder;
- private LayoutInflater inflater;
-
- public OrganisationDialog(Context context) {
- dialogBuilder = new AlertDialog.Builder(context);
- inflater = ((Activity)context).getLayoutInflater();
- }
-
- public void createInfoDialog(Organisation org) {
-
- View dialogContent = inflater.inflate(R.layout.view_holder_organisation, null);
- dialogBuilder.setView(dialogContent);
-
- TextView title = dialogContent.findViewById(R.id.organisation_title);
- title.setText(org.getName());
-
- TextView uuid = dialogContent.findViewById(R.id.organisation_uuid);
- uuid.setText(org.getUuid());
-
- TextView description = dialogContent.findViewById(R.id.organisation_description);
- description.setText(org.getDescription());
-
- TextView sector = dialogContent.findViewById(R.id.organisation_sector);
- sector.setText(org.getSector());
-
- TextView nationality = dialogContent.findViewById(R.id.organisation_nationality);
- nationality.setText(org.getNationality());
-
- TextView userCount = dialogContent.findViewById(R.id.organisation_user_count);
- userCount.setText("" + org.getUserCount());
-
- dialogBuilder.setPositiveButton("OK", null);
- dialogBuilder.setCancelable(true);
- dialogBuilder.create().show();
- }
-
- public void createAcceptDialog(Organisation org, final DialogCallback callback) {
- View dialogContent = inflater.inflate(R.layout.view_holder_organisation, null);
- dialogBuilder.setView(dialogContent);
-
- TextView title = dialogContent.findViewById(R.id.organisation_title);
- title.setText(org.getName());
-
- TextView uuid = dialogContent.findViewById(R.id.organisation_uuid);
- uuid.setText(org.getUuid());
-
- TextView description = dialogContent.findViewById(R.id.organisation_description);
- description.setText(org.getDescription());
-
- TextView sector = dialogContent.findViewById(R.id.organisation_sector);
- sector.setText(org.getSector());
-
- TextView nationality = dialogContent.findViewById(R.id.organisation_nationality);
- nationality.setText(org.getNationality());
-
- TextView userCount = dialogContent.findViewById(R.id.organisation_user_count);
- userCount.setText("" + org.getUserCount());
-
- dialogBuilder.setNegativeButton("REJECT", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- callback.onReject();
- }
- });
- dialogBuilder.setPositiveButton("ACCEPT", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- callback.onAccept();
- }
- });
-
- dialogBuilder.setCancelable(false);
- dialogBuilder.create().show();
- }
-
- public interface DialogCallback {
- void onAccept();
- void onReject();
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/PreferenceManager.java b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/PreferenceManager.java
index 9efd6b2..74d73a1 100644
--- a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/PreferenceManager.java
+++ b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/PreferenceManager.java
@@ -2,31 +2,72 @@ package de.overview.wg.its.mispauth.auxiliary;
import android.content.Context;
import android.content.SharedPreferences;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
import de.overview.wg.its.mispauth.model.Organisation;
+import de.overview.wg.its.mispauth.model.SyncedPartner;
import de.overview.wg.its.mispauth.model.User;
import org.json.JSONException;
import org.json.JSONObject;
+import java.lang.reflect.Type;
+import java.util.List;
+
public class PreferenceManager {
private static PreferenceManager instance;
- private SharedPreferences sharedPreferences;
+
+ private SharedPreferences userPreferences;
+ private SharedPreferences credentialPreferences;
+ private SharedPreferences syncedInstancesPreferences;
+
+ private static final String CREDENTIAL_PREFERENCE = "de.overview.wg.its.mispauth.credential_preference";
+ private static final String SAVED_INSTANCES_PREFERENCE = "de.overview.wg.its.mispauth.saved_instances_preference";
+ private static final String USER_PREFERENCE = "de.overview.wg.its.mispauth.user_preferences";
private static String PREF_KEY_SERVER_URL = "key_server_url";
private static String PREF_KEY_SERVER_API_KEY = "key_server_api_key";
private static String PREF_KEY_MY_ORGANISATION = "key_my_organisation";
private static String PREF_KEY_MY_USER = "key_my_user";
+ private static String PREF_KEY_SAVE_AUTHKEY_ENABLED = "key_save_authkey_enabled";
+ private static String PREF_KEY_SYNCED_ORGANISATIONS = "key_synced_organisations";
private PreferenceManager(Context context) {
- sharedPreferences = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
+ credentialPreferences = context.getSharedPreferences(CREDENTIAL_PREFERENCE, Context.MODE_PRIVATE);
+ syncedInstancesPreferences = context.getSharedPreferences(SAVED_INSTANCES_PREFERENCE, Context.MODE_PRIVATE);
+ userPreferences = context.getSharedPreferences(USER_PREFERENCE, Context.MODE_PRIVATE);
}
+ public List getSyncedPartnerList() {
+ String list = syncedInstancesPreferences.getString(PREF_KEY_SYNCED_ORGANISATIONS, "");
+ Type type = new TypeToken>() {}.getType();
+ return new Gson().fromJson(list, type);
+ }
+ public void setSyncedPartnerList(List syncedPartnerList) {
+ String json = new Gson().toJson(syncedPartnerList);
+ SharedPreferences.Editor editor = syncedInstancesPreferences.edit();
+ editor.putString(PREF_KEY_SYNCED_ORGANISATIONS, json);
+ editor.apply();
+ }
+
+ public boolean saveAuthkeyEnabledExists() {
+ return userPreferences.contains(PREF_KEY_SAVE_AUTHKEY_ENABLED);
+ }
+ public boolean saveAuthkeyEnabled() {
+ return userPreferences.getBoolean(PREF_KEY_SAVE_AUTHKEY_ENABLED, false);
+ }
+ public void setSaveAuthkeyEnabled(boolean save) {
+ SharedPreferences.Editor editor = userPreferences.edit();
+ editor.putBoolean(PREF_KEY_SAVE_AUTHKEY_ENABLED, save);
+ editor.apply();
+ }
+
/**
* @return own Organisation if available, else null
*/
public Organisation getMyOrganisation() {
try {
- JSONObject jsonObject = new JSONObject(sharedPreferences.getString(PREF_KEY_MY_ORGANISATION, ""));
+ JSONObject jsonObject = new JSONObject(credentialPreferences.getString(PREF_KEY_MY_ORGANISATION, ""));
Organisation org = new Organisation();
org.fromJSON(jsonObject);
return org;
@@ -37,14 +78,14 @@ public class PreferenceManager {
return null;
}
public void setMyOrganisation(Organisation org) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
+ SharedPreferences.Editor editor = credentialPreferences.edit();
editor.putString(PREF_KEY_MY_ORGANISATION, org.toJSON().toString());
editor.apply();
}
public User getMyUser() {
try {
- JSONObject jsonObject = new JSONObject(sharedPreferences.getString(PREF_KEY_MY_USER, ""));
+ JSONObject jsonObject = new JSONObject(credentialPreferences.getString(PREF_KEY_MY_USER, ""));
User user = new User();
user.fromJSON(jsonObject);
return user;
@@ -55,34 +96,40 @@ public class PreferenceManager {
return null;
}
public void setMyUser(User user) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
+ SharedPreferences.Editor editor = credentialPreferences.edit();
editor.putString(PREF_KEY_MY_USER, user.toJSON().toString());
editor.apply();
}
public String getMyServerUrl() {
- return sharedPreferences.getString(PREF_KEY_SERVER_URL, "");
+ return credentialPreferences.getString(PREF_KEY_SERVER_URL, "");
}
public void setMyServerUrl(String serverUrl) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
+ SharedPreferences.Editor editor = credentialPreferences.edit();
editor.putString(PREF_KEY_SERVER_URL, serverUrl);
editor.apply();
}
public String getMyServerApiKey() {
- return sharedPreferences.getString(PREF_KEY_SERVER_API_KEY, "");
+ return credentialPreferences.getString(PREF_KEY_SERVER_API_KEY, "");
}
public void setMyServerApiKey(String apiKey) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
+ SharedPreferences.Editor editor = credentialPreferences.edit();
editor.putString(PREF_KEY_SERVER_API_KEY, apiKey);
editor.apply();
}
- public void deleteAllLocalData() {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.clear();
- editor.apply();
+
+ public void clearUserPreferences() {
+ userPreferences.edit().clear().apply();
}
+ public void clearCredentialPreferences() {
+ credentialPreferences.edit().clear().apply();
+ }
+ public void clearSyncedInformationPreferences() {
+ syncedInstancesPreferences.edit().clear().apply();
+ }
+
public static PreferenceManager Instance(Context context) {
if(instance == null) {
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/RandomString.java b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/RandomString.java
new file mode 100644
index 0000000..6a26fec
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/RandomString.java
@@ -0,0 +1,51 @@
+package de.overview.wg.its.mispauth.auxiliary;
+
+import java.security.SecureRandom;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Random;
+
+public class RandomString {
+
+ private static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String lower = upper.toLowerCase(Locale.ROOT);
+ private static final String digits = "0123456789";
+ private static final String alphaNum = upper + lower + digits;
+
+ private final Random random;
+ private final char[] symbols;
+ private final char[] buf;
+
+ public RandomString(int length, Random random, String symbols) {
+
+ if (length < 1) {
+ throw new IllegalArgumentException();
+ }
+ if (symbols.length() < 2) {
+ throw new IllegalArgumentException();
+ }
+
+ this.random = Objects.requireNonNull(random);
+ this.symbols = symbols.toCharArray();
+ this.buf = new char[length];
+
+ }
+
+ public RandomString(int length, Random random) {
+ this(length, random, alphaNum);
+ }
+
+ public RandomString(int length) {
+ this(length, new SecureRandom());
+ }
+
+ public String nextString() {
+
+ for (int idx = 0; idx < buf.length; ++idx) {
+ buf[idx] = symbols[random.nextInt(symbols.length)];
+ }
+
+ return new String(buf);
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/TempAuth.java b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/TempAuth.java
new file mode 100644
index 0000000..ed23b81
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/auxiliary/TempAuth.java
@@ -0,0 +1,7 @@
+package de.overview.wg.its.mispauth.auxiliary;
+
+public class TempAuth {
+
+ public static String TMP_AUTH_KEY;
+
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/cam/AutoFitTextureView.java b/app/src/main/java/de/overview/wg/its/mispauth/cam/AutoFitTextureView.java
new file mode 100644
index 0000000..d2305e8
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/cam/AutoFitTextureView.java
@@ -0,0 +1,76 @@
+package de.overview.wg.its.mispauth.cam;
+
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * 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.
+ */
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.TextureView;
+
+/**
+ * A {@link TextureView} that can be adjusted to a specified aspect ratio.
+ */
+public class AutoFitTextureView extends TextureView {
+
+ private int mRatioWidth = 0;
+ private int mRatioHeight = 0;
+
+ public AutoFitTextureView(Context context) {
+ this(context, null);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
+ * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
+ * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
+ *
+ * @param width Relative horizontal size
+ * @param height Relative vertical size
+ */
+ public void setAspectRatio(int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Size cannot be negative.");
+ }
+ mRatioWidth = width;
+ mRatioHeight = height;
+ requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ if (0 == mRatioWidth || 0 == mRatioHeight) {
+ setMeasuredDimension(width, height);
+ } else {
+ if (width < height * mRatioWidth / mRatioHeight) {
+ setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
+ } else {
+ setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/cam/CameraFragment.java b/app/src/main/java/de/overview/wg/its/mispauth/cam/CameraFragment.java
new file mode 100644
index 0000000..4d05141
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/cam/CameraFragment.java
@@ -0,0 +1,929 @@
+package de.overview.wg.its.mispauth.cam;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.graphics.*;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.renderscript.*;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v4.content.ContextCompat;
+import android.util.Log;
+import android.util.Size;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.view.*;
+import android.widget.Toast;
+import com.google.android.gms.vision.Frame;
+import com.google.android.gms.vision.barcode.Barcode;
+import com.google.android.gms.vision.barcode.BarcodeDetector;
+import de.overview.wg.its.mispauth.SyncActivity;
+import de.overview.wg.its.mispauth.R;
+import de.overview.wg.its.mispauth.auxiliary.AESSecurity;
+import de.overview.wg.its.mispauth.model.PublicKeyQr;
+import de.overview.wg.its.mispauth.model.SyncInformationQr;
+import org.json.JSONException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class CameraFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback {
+
+ private SyncActivity parentActivity;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ parentActivity = (SyncActivity) context;
+ }
+
+ /**
+ * Conversion from screen rotation to JPEG orientation.
+ */
+ private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+ private static final int REQUEST_CAMERA_PERMISSION = 1;
+ private static final String FRAGMENT_DIALOG = "dialog";
+
+ static {
+ ORIENTATIONS.append(Surface.ROTATION_0, 90);
+ ORIENTATIONS.append(Surface.ROTATION_90, 0);
+ ORIENTATIONS.append(Surface.ROTATION_180, 270);
+ ORIENTATIONS.append(Surface.ROTATION_270, 180);
+ }
+
+ /**
+ * Tag for the {@link Log}.
+ */
+ private static final String TAG = "MISP_LOGGING";
+
+ /**
+ * Max preview width that is guaranteed by Camera2 API
+ */
+ private static final int MAX_PREVIEW_WIDTH = 1920;
+
+ /**
+ * Max preview height that is guaranteed by Camera2 API
+ */
+ private static final int MAX_PREVIEW_HEIGHT = 1080;
+
+ /**
+ * {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
+ * {@link TextureView}.
+ */
+ private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
+ openCamera(width, height);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
+ configureTransform(width, height);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture texture) {
+ }
+
+ };
+
+ /**
+ * ID of the current {@link CameraDevice}.
+ */
+ private String mCameraId;
+
+ /**
+ * An {@link AutoFitTextureView} for camera preview.
+ */
+ private AutoFitTextureView mTextureView;
+
+ /**
+ * A {@link CameraCaptureSession } for camera preview.
+ */
+ private CameraCaptureSession mCaptureSession;
+
+ /**
+ * A reference to the opened {@link CameraDevice}.
+ */
+ private CameraDevice mCameraDevice;
+
+ /**
+ * The {@link android.util.Size} of camera preview.
+ */
+ private Size mPreviewSize;
+
+ /**
+ * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state.
+ */
+ private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
+
+ @Override
+ public void onOpened(@NonNull CameraDevice cameraDevice) {
+ // This method is called when the camera is opened. We start camera preview here.
+ mCameraOpenCloseLock.release();
+ mCameraDevice = cameraDevice;
+ createCameraPreviewSession();
+ }
+
+ @Override
+ public void onDisconnected(@NonNull CameraDevice cameraDevice) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ }
+
+ @Override
+ public void onError(@NonNull CameraDevice cameraDevice, int error) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ Activity activity = getActivity();
+ if (null != activity) {
+ activity.finish();
+ }
+ }
+
+ };
+
+ /**
+ * An additional thread for running tasks that shouldn't block the UI.
+ */
+ private HandlerThread mBackgroundThread;
+
+ /**
+ * A {@link Handler} for running tasks in the background.
+ */
+ private Handler mBackgroundHandler;
+
+ /**
+ * An {@link ImageReader} that handles still image capture.
+ */
+ private ImageReader mImageReader;
+
+ /**
+ * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
+ * still image is ready to be saved.
+ */
+ private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+
+ Image image = reader.acquireNextImage();
+ Bitmap bitmap = YUV2Bitmap(image);
+
+// final Bitmap bitmap = invertBitmap(YUV2Bitmap(image));
+
+ if (bitmap != null) {
+
+ if (readQrEnabled) {
+
+ Frame frame = new Frame.Builder().setBitmap(bitmap).build();
+ SparseArray barcodes = barcodeDetector.detect(frame);
+
+ if (barcodes.size() > 0) {
+ if (currentScanMode == ScanMode.PUBLIC_KEY) {
+ returnPublicKey(barcodes.valueAt(0).rawValue);
+ } else {
+ returnSyncInformation(barcodes.valueAt(0).rawValue);
+ }
+ }
+ }
+ }
+
+ if (image != null) {
+ image.close();
+ }
+ }
+
+ };
+
+ /**
+ * {@link CaptureRequest.Builder} for the camera preview
+ */
+ private CaptureRequest.Builder mPreviewRequestBuilder;
+
+ /**
+ * {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder}
+ */
+ private CaptureRequest mPreviewRequest;
+
+ /**
+ * A {@link Semaphore} to prevent the app from exiting before closing the camera.
+ */
+ private Semaphore mCameraOpenCloseLock = new Semaphore(1);
+
+ /**
+ * Shows a {@link Toast} on the UI thread.
+ *
+ * @param text The message to show
+ */
+ private void showToast(final String text) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+
+ /**
+ * Given {@code choices} of {@code Size}s supported by a camera, choose the smallest one that
+ * is at least as large as the respective texture view size, and that is at most as large as the
+ * respective max size, and whose aspect ratio matches with the specified value. If such size
+ * doesn't exist, choose the largest one that is at most as large as the respective max size,
+ * and whose aspect ratio matches with the specified value.
+ *
+ * @param choices The list of sizes that the camera supports for the intended output
+ * class
+ * @param textureViewWidth The width of the texture view relative to sensor coordinate
+ * @param textureViewHeight The height of the texture view relative to sensor coordinate
+ * @param maxWidth The maximum width that can be chosen
+ * @param maxHeight The maximum height that can be chosen
+ * @param aspectRatio The aspect ratio
+ * @return The optimal {@code Size}, or an arbitrary one if none were big enough
+ */
+ private static Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
+
+ // Collect the supported resolutions that are at least as big as the preview Surface
+ List bigEnough = new ArrayList<>();
+ // Collect the supported resolutions that are smaller than the preview Surface
+ List notBigEnough = new ArrayList<>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight && option.getHeight() == option.getWidth() * h / w) {
+ if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
+ bigEnough.add(option);
+ } else {
+ notBigEnough.add(option);
+ }
+ }
+ }
+
+ // Pick the smallest of those big enough. If there is no one big enough, pick the
+ // largest of those not big enough.
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else if (notBigEnough.size() > 0) {
+ return Collections.max(notBigEnough, new CompareSizesByArea());
+ } else {
+ Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
+ public static CameraFragment newInstance(ScanMode mode) {
+
+ CameraFragment f = new CameraFragment();
+
+ Bundle args = new Bundle();
+ args.putSerializable(BUNDLE_MODE_KEY, mode);
+ f.setArguments(args);
+
+ return f;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View v = inflater.inflate(R.layout.fragment_camera, container, false);
+
+ initRenderScript();
+
+ setUpBarcodeDetector();
+ checkBundle();
+
+ return v;
+ }
+
+ @Override
+ public void onViewCreated(final View view, Bundle savedInstanceState) {
+ mTextureView = view.findViewById(R.id.texture);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ startBackgroundThread();
+
+ // When the screen is turned off and turned back on, the SurfaceTexture is already
+ // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
+ // a camera and start preview from here (otherwise, we wait until the surface is ready in
+ // the SurfaceTextureListener).
+ if (mTextureView.isAvailable()) {
+ openCamera(mTextureView.getWidth(), mTextureView.getHeight());
+ } else {
+ mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ closeCamera();
+ stopBackgroundThread();
+ super.onPause();
+ }
+
+ private void requestCameraPermission() {
+ if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
+ new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
+ } else {
+ requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == REQUEST_CAMERA_PERMISSION) {
+ if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ ErrorDialog.newInstance("REQUEST PERMISSION").show(getChildFragmentManager(), FRAGMENT_DIALOG);
+ }
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+ }
+
+ /**
+ * Sets up member variables related to camera.
+ *
+ * @param width The width of available size for camera preview
+ * @param height The height of available size for camera preview
+ */
+ @SuppressWarnings("SuspiciousNameCombination")
+ private void setUpCameraOutputs(int width, int height) {
+ Activity activity = getActivity();
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+
+ try {
+ for (String cameraId : manager.getCameraIdList()) {
+ CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
+
+ // We don't use a front facing camera in this sample.
+ Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
+ continue;
+ }
+
+ StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ if (map == null) {
+ continue;
+ }
+
+ // For still image captures, we use the largest available size.
+ Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)), new CompareSizesByArea());
+
+ mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);
+ mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
+
+ // Find out if we need to swap dimension to get the preview size relative to sensor coordinate.
+ int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ //noinspection ConstantConditions
+ int mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
+ boolean swappedDimensions = false;
+ switch (displayRotation) {
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_180:
+ if (mSensorOrientation == 90 || mSensorOrientation == 270) {
+ swappedDimensions = true;
+ }
+ break;
+ case Surface.ROTATION_90:
+ case Surface.ROTATION_270:
+ if (mSensorOrientation == 0 || mSensorOrientation == 180) {
+ swappedDimensions = true;
+ }
+ break;
+ default:
+ Log.e(TAG, "Display rotation is invalid: " + displayRotation);
+ }
+
+ Point displaySize = new Point();
+ activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
+
+ int rotatedPreviewWidth = width;
+ int rotatedPreviewHeight = height;
+ int maxPreviewWidth = displaySize.x;
+ int maxPreviewHeight = displaySize.y;
+
+ if (swappedDimensions) {
+ rotatedPreviewWidth = height;
+ rotatedPreviewHeight = width;
+ maxPreviewWidth = displaySize.y;
+ maxPreviewHeight = displaySize.x;
+ }
+
+ if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
+ maxPreviewWidth = MAX_PREVIEW_WIDTH;
+ }
+
+ if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
+ maxPreviewHeight = MAX_PREVIEW_HEIGHT;
+ }
+
+ // Danger, W.R.! Attempting to use too large a preview size could exceed the camera
+ // bus' bandwidth limitation, resulting in gorgeous previews but the storage of
+ // garbage capture data.
+ mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
+ rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
+ maxPreviewHeight, largest);
+
+ // We fit the aspect ratio of TextureView to the size of preview we picked.
+ int orientation = getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+ } else {
+ mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ }
+
+ mCameraId = cameraId;
+ return;
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ // Currently an NPE is thrown when the Camera2API is used but not supported on the
+ // device this code runs.
+ ErrorDialog.newInstance("CAMERA ERROR").show(getChildFragmentManager(), FRAGMENT_DIALOG);
+ }
+ }
+
+ /**
+ * Opens the camera specified by {@link CameraFragment#mCameraId}.
+ */
+ private void openCamera(int width, int height) {
+
+ if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ requestCameraPermission();
+ return;
+ }
+
+ setUpCameraOutputs(width, height);
+ configureTransform(width, height);
+
+ Activity activity = getActivity();
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+
+ try {
+
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Time out waiting to lock camera opening.");
+ }
+
+ manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
+ }
+ }
+
+ /**
+ * Closes the current {@link CameraDevice}.
+ */
+ private void closeCamera() {
+ try {
+ mCameraOpenCloseLock.acquire();
+
+ if (null != mCaptureSession) {
+ mCaptureSession.close();
+ mCaptureSession = null;
+ }
+
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+
+ if (null != mImageReader) {
+ mImageReader.close();
+ mImageReader = null;
+ }
+
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
+ } finally {
+ mCameraOpenCloseLock.release();
+ }
+ }
+
+ /**
+ * Starts a background thread and its {@link Handler}.
+ */
+ private void startBackgroundThread() {
+ mBackgroundThread = new HandlerThread("CameraBackground");
+ mBackgroundThread.start();
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
+ }
+
+ /**
+ * Stops the background thread and its {@link Handler}.
+ */
+ private void stopBackgroundThread() {
+ mBackgroundThread.quitSafely();
+ try {
+ mBackgroundThread.join();
+ mBackgroundThread = null;
+ mBackgroundHandler = null;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a new {@link CameraCaptureSession} for camera preview.
+ */
+ private void createCameraPreviewSession() {
+ try {
+ SurfaceTexture texture = mTextureView.getSurfaceTexture();
+ assert texture != null;
+
+ // We configure the size of default buffer to be the size of camera preview we want.
+ texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+
+ // This is the output Surface we need to start preview.
+ Surface surface = new Surface(texture);
+ Surface mImageSurface = mImageReader.getSurface();
+
+ // We set up a CaptureRequest.Builder with the output Surface.
+ mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mPreviewRequestBuilder.addTarget(surface);
+ mPreviewRequestBuilder.addTarget(mImageSurface);
+
+ // Here, we create a CameraCaptureSession for camera preview.
+ mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
+ new CameraCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
+ // The camera is already closed
+ if (null == mCameraDevice) {
+ return;
+ }
+
+ // When the session is ready, we start displaying the preview.
+ mCaptureSession = cameraCaptureSession;
+ try {
+ // Auto focus should be continuous for camera preview.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+
+ // Finally, we start displaying the camera preview.
+ mPreviewRequest = mPreviewRequestBuilder.build();
+ mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
+ showToast("Failed");
+ }
+ }, null
+ );
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
+ * This method should be called after the camera preview size is determined in
+ * setUpCameraOutputs and also the size of `mTextureView` is fixed.
+ *
+ * @param viewWidth The width of `mTextureView`
+ * @param viewHeight The height of `mTextureView`
+ */
+ private void configureTransform(int viewWidth, int viewHeight) {
+ Activity activity = getActivity();
+
+ if (null == mTextureView || null == mPreviewSize || null == activity) {
+ return;
+ }
+
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ Matrix matrix = new Matrix();
+ RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ float centerX = viewRect.centerX();
+ float centerY = viewRect.centerY();
+ if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
+ float scale = Math.max(
+ (float) viewHeight / mPreviewSize.getHeight(),
+ (float) viewWidth / mPreviewSize.getWidth());
+ matrix.postScale(scale, scale, centerX, centerY);
+ matrix.postRotate(90 * (rotation - 2), centerX, centerY);
+ } else if (Surface.ROTATION_180 == rotation) {
+ matrix.postRotate(180, centerX, centerY);
+ }
+ mTextureView.setTransform(matrix);
+ }
+
+ /**
+ * Compares two {@code Size}s based on their areas.
+ */
+ static class CompareSizesByArea implements Comparator {
+
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
+ }
+
+ }
+
+
+ /**
+ * Shows an error message dialog.
+ */
+ public static class ErrorDialog extends DialogFragment {
+
+ private static final String ARG_MESSAGE = "message";
+
+ public static ErrorDialog newInstance(String message) {
+ ErrorDialog dialog = new ErrorDialog();
+ Bundle args = new Bundle();
+ args.putString(ARG_MESSAGE, message);
+ dialog.setArguments(args);
+ return dialog;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Activity activity = getActivity();
+ return new AlertDialog.Builder(activity)
+ .setMessage(getArguments().getString(ARG_MESSAGE))
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ activity.finish();
+ }
+ })
+ .create();
+ }
+
+ }
+
+ /**
+ * Shows OK/Cancel confirmation dialog about camera permission.
+ */
+ public static class ConfirmationDialog extends DialogFragment {
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Fragment parent = getParentFragment();
+ return new AlertDialog.Builder(getActivity())
+ .setMessage("REQUEST PERMISSION")
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ parent.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Activity activity = parent.getActivity();
+ if (activity != null) {
+ activity.finish();
+ }
+ }
+ })
+ .create();
+ }
+ }
+
+
+ private static final String BUNDLE_MODE_KEY = "mode";
+
+ public enum ScanMode {
+ PUBLIC_KEY,
+ INFO
+ }
+
+ private ScanMode currentScanMode;
+ private boolean readQrEnabled = true;
+ private BarcodeDetector barcodeDetector;
+
+ private RenderScript renderScript;
+ private static final Matrix4f TRANSFORMATION_MATRIX = new Matrix4f(new float[]{
+ -0.33f, -0.33f, -0.33f, 1.0f,
+ -0.59f, -0.59f, -0.59f, 1.0f,
+ -0.11f, -0.11f, -0.11f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f
+ });
+
+ private void initRenderScript() {
+ renderScript = RenderScript.create(getActivity());
+ }
+
+ private Bitmap YUV2Bitmap(Image image) {
+
+ if (image == null) {
+ return null;
+ }
+
+ ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(renderScript, Element.U8_4(renderScript));
+
+ int W = image.getWidth();
+ int H = image.getHeight();
+
+ Image.Plane Y = image.getPlanes()[0];
+ Image.Plane U = image.getPlanes()[1];
+ Image.Plane V = image.getPlanes()[2];
+
+ int Yb = Y.getBuffer().remaining();
+ int Ub = U.getBuffer().remaining();
+ int Vb = V.getBuffer().remaining();
+
+ byte[] data = new byte[Yb + Ub + Vb];
+
+ Y.getBuffer().get(data, 0, Yb);
+ V.getBuffer().get(data, Yb, Vb);
+ U.getBuffer().get(data, Yb + Vb, Ub);
+
+ Type.Builder yuvType = new Type.Builder(renderScript, Element.U8(renderScript)).setX(data.length);
+ Allocation in = Allocation.createTyped(renderScript, yuvType.create(), Allocation.USAGE_SCRIPT);
+
+ Type.Builder rgbaType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript)).setX(W).setY(H);
+ Allocation out = Allocation.createTyped(renderScript, rgbaType.create(), Allocation.USAGE_SCRIPT);
+
+ final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);
+
+ in.copyFromUnchecked(data);
+
+ yuvToRgbIntrinsic.setInput(in);
+ yuvToRgbIntrinsic.forEach(out);
+
+ out.copyTo(bmpout);
+ image.close();
+
+ return bmpout;
+ }
+
+ private Bitmap invertBitmap(Bitmap source) {
+
+ final Bitmap result = source.copy(source.getConfig(), true);
+ Allocation input = Allocation.createFromBitmap(renderScript, source, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
+ Allocation output = Allocation.createTyped(renderScript, input.getType());
+
+ final ScriptIntrinsicColorMatrix inverter = ScriptIntrinsicColorMatrix.create(renderScript);
+ inverter.setColorMatrix(TRANSFORMATION_MATRIX);
+ inverter.forEach(input, output);
+ output.copyTo(result);
+
+ source.recycle();
+ renderScript.destroy();
+
+ return result;
+ }
+
+ private void setReadQrEnabled(boolean enabled) {
+ readQrEnabled = enabled;
+ }
+
+ private void checkBundle() {
+ Bundle args = getArguments();
+
+ if (args != null) {
+ currentScanMode = (ScanMode) args.getSerializable(BUNDLE_MODE_KEY);
+ }
+ }
+
+ private void returnPublicKey(String qrData) {
+
+ setReadQrEnabled(false);
+
+ try {
+ final PublicKeyQr pkqr = new PublicKeyQr(qrData);
+// parentActivity.qrVisible(false, 300);
+
+ DialogInterface.OnClickListener positive = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+
+ parentActivity.onPublicKeyResult(pkqr);
+// parentActivity.qrVisible(true, 800);
+
+ closeCamera();
+
+ parentActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextureView.setVisibility(View.GONE);
+ }
+ });
+ }
+ };
+
+ DialogInterface.OnClickListener negative = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+// parentActivity.qrVisible(true, 800);
+ setReadQrEnabled(true);
+ }
+ };
+
+ DialogFactory diaFac = new DialogFactory(parentActivity);
+ diaFac.createKeyDialog(pkqr, positive, negative).show();
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void returnSyncInformation(String qrData) {
+
+ setReadQrEnabled(false);
+
+ AESSecurity aesSecurity = AESSecurity.getInstance();
+ String decryptedQrData = aesSecurity.decrypt(qrData);
+
+ final SyncInformationQr siqr;
+
+ try {
+ siqr = new SyncInformationQr(decryptedQrData);
+
+ DialogInterface.OnClickListener positive = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ parentActivity.onSyncInfoResult(siqr);
+
+ closeCamera();
+
+ parentActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTextureView.setVisibility(View.GONE);
+ }
+ });
+ }
+ };
+
+ DialogInterface.OnClickListener negative = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ setReadQrEnabled(true);
+ }
+ };
+
+ DialogFactory diaFac = new DialogFactory(parentActivity);
+ diaFac.createInformationDialog(siqr, positive, negative).show();
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ private void setUpBarcodeDetector() {
+ barcodeDetector = new BarcodeDetector.Builder(getActivity())
+ .setBarcodeFormats(Barcode.QR_CODE)
+ .build();
+
+ if (!barcodeDetector.isOperational()) {
+ Toast.makeText(getActivity(), "Could not setup QR-Code scanner!", Toast.LENGTH_SHORT).show();
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/cam/DialogFactory.java b/app/src/main/java/de/overview/wg/its/mispauth/cam/DialogFactory.java
new file mode 100644
index 0000000..9a944b9
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/cam/DialogFactory.java
@@ -0,0 +1,136 @@
+package de.overview.wg.its.mispauth.cam;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.*;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import de.overview.wg.its.mispauth.R;
+import de.overview.wg.its.mispauth.model.PublicKeyQr;
+import de.overview.wg.its.mispauth.model.SyncInformationQr;
+
+public class DialogFactory {
+
+ private Context context;
+
+ private AlertDialog.Builder adb;
+ private LayoutInflater inflater;
+
+
+ public DialogFactory(Context context) {
+ this.context = context;
+ adb = new AlertDialog.Builder(context);
+ inflater = LayoutInflater.from(context);
+ }
+
+
+ public Dialog createKeyDialog(PublicKeyQr pkqr,
+ DialogInterface.OnClickListener positiveListener,
+ DialogInterface.OnClickListener negativeListener) {
+
+ View title = inflater.inflate(R.layout.dialog_public_key, null);
+ adb.setCustomTitle(title);
+
+ adb.setMessage("\nYou received a Public Key from " + pkqr.getOrganisation() + " (" + pkqr.getUser() + ")");
+
+ adb.setPositiveButton(context.getResources().getString(R.string.accept), positiveListener);
+ adb.setNegativeButton(context.getResources().getString(R.string.reject), negativeListener);
+
+ adb.setCancelable(false);
+
+ Dialog d = adb.create();
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+ d.getWindow().setDimAmount(0.8f);
+ return d;
+ }
+
+
+ public Dialog createInformationDialog(SyncInformationQr siqr,
+ DialogInterface.OnClickListener positiv,
+ DialogInterface.OnClickListener negativ) {
+
+ View title = inflater.inflate(R.layout.dialog_sync_info, null);
+ adb.setCustomTitle(title);
+
+ View orgView = inflater.inflate(R.layout.view_organisation, null);
+
+ TextView orgTitle = orgView.findViewById(R.id.organisation_title);
+ orgTitle.setText(siqr.getOrganisation().getName());
+
+ TextView orgUuid = orgView.findViewById(R.id.organisation_uuid);
+ orgUuid.setText(siqr.getOrganisation().getUuid());
+
+ TextView orgDesc = orgView.findViewById(R.id.organisation_description);
+ orgDesc.setText(siqr.getOrganisation().getDescription());
+
+ TextView orgNat = orgView.findViewById(R.id.organisation_nationality);
+ orgNat.setText(siqr.getOrganisation().getNationality());
+
+ TextView orgSec = orgView.findViewById(R.id.organisation_sector);
+ orgSec.setText(siqr.getOrganisation().getSector());
+
+ TextView orgUser = orgView.findViewById(R.id.organisation_user_count);
+ orgUser.setText("" + siqr.getOrganisation().getUserCount());
+
+ adb.setView(orgView);
+
+ adb.setPositiveButton(context.getResources().getString(R.string.accept), positiv);
+ adb.setNegativeButton(context.getResources().getString(R.string.reject), negativ);
+
+ Dialog d = adb.create();
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+ d.getWindow().setDimAmount(0.8f);
+ return d;
+ }
+
+
+ public Dialog createDeleteDialog(DialogInterface.OnClickListener pos,
+ DialogInterface.OnClickListener neg) {
+ adb.setTitle(context.getResources().getString(R.string.delete_local_data));
+ adb.setMessage(context.getResources().getString(R.string.delete_local_data_msg));
+
+ adb.setPositiveButton(context.getResources().getString(R.string.delete), pos);
+ adb.setNegativeButton(android.R.string.cancel, neg);
+
+ adb.setCancelable(true);
+ Dialog d = adb.create();
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+ return d;
+ }
+
+ public Dialog createSelectDeleteDialog(DialogInterface.OnClickListener pos,
+ DialogInterface.OnClickListener neg) {
+
+ adb.setTitle("Delete local data");
+ adb.setMessage("");
+
+ adb.setPositiveButton(context.getResources().getString(R.string.delete), pos);
+ adb.setNegativeButton(android.R.string.cancel, neg);
+
+ adb.setCancelable(true);
+ Dialog d = adb.create();
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+ return d;
+ }
+
+
+ public Dialog createOverrideDialog(DialogInterface.OnClickListener pos,
+ DialogInterface.OnClickListener neg) {
+
+ adb.setTitle(context.getResources().getString(R.string.override_local_data));
+ adb.setMessage(context.getResources().getString(R.string.override_local_data_msg));
+
+ adb.setPositiveButton(context.getResources().getString(R.string.override), pos);
+ adb.setNegativeButton(android.R.string.cancel, null);
+
+ Dialog d = adb.create();
+
+ d.setCancelable(false);
+ d.getWindow().setWindowAnimations(R.style.DialogAnimation);
+
+ return d;
+ }
+
+
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/fragment/ReviewQrFragment.java b/app/src/main/java/de/overview/wg/its/mispauth/fragment/ReviewQrFragment.java
deleted file mode 100644
index fe1cd04..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/fragment/ReviewQrFragment.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.overview.wg.its.mispauth.fragment;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import de.overview.wg.its.mispauth.R;
-
-public class ReviewQrFragment extends Fragment {
-
- @Nullable
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_review_qr, null);
- return v;
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/fragment/ScanQrFragment.java b/app/src/main/java/de/overview/wg/its/mispauth/fragment/ScanQrFragment.java
deleted file mode 100644
index b7ce186..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/fragment/ScanQrFragment.java
+++ /dev/null
@@ -1,361 +0,0 @@
-package de.overview.wg.its.mispauth.fragment;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
-import android.graphics.ImageFormat;
-import android.graphics.SurfaceTexture;
-import android.hardware.camera2.*;
-import android.hardware.camera2.params.StreamConfigurationMap;
-import android.media.Image;
-import android.media.ImageReader;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.renderscript.*;
-import android.support.annotation.NonNull;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.app.Fragment;
-import android.support.v4.content.ContextCompat;
-import android.util.Size;
-import android.util.SparseArray;
-import android.view.*;
-import android.widget.Toast;
-import com.google.android.gms.vision.Frame;
-import com.google.android.gms.vision.barcode.Barcode;
-import com.google.android.gms.vision.barcode.BarcodeDetector;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.activity.SyncActivity;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class ScanQrFragment extends Fragment {
-
- private static final int CAMERA_REQUEST_CODE = 0;
-
- private HandlerThread backgroundThread;
- private Handler backgroundHandler;
-
- private CameraManager cameraManager;
- private CameraDevice cameraDevice;
- private String cameraID;
- private CameraCaptureSession cameraCaptureSession;
-
- private SurfaceTexture previewSurfaceTexture;
- private Surface previewSurface, yuvSurface;
- private Size[] yuvSizes;
-
- private BarcodeDetector barcodeDetector;
- private TextureView previewView;
-
- private boolean readQr = true;
-
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_sync_scan, null);
-
- previewView = v.findViewById(R.id.texture_scan_preview);
-
- if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
-
- if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA)) {
-
- } else {
- ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
- }
-
- } else {
- setUpBarcodeDetector();
- setUpPreviewTexture();
- }
-
- return v;
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
- switch (requestCode) {
- case CAMERA_REQUEST_CODE: {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- setUpBarcodeDetector();
- setUpPreviewTexture();
- } else {
- Toast.makeText(getActivity(), "Camera permission needed!", Toast.LENGTH_SHORT).show();
- }
- }
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- openBackgroundThread();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- closeCamera();
- closeBackgroundThread();
- }
-
-
- private void returnResult(String qrData) {
- ((SyncActivity) getActivity()).setScannedQr(qrData);
- }
-
- private void setUpPreviewTexture() {
-
- previewView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- surface.setDefaultBufferSize(width, height);
- previewSurfaceTexture = surface;
- setUpCamera();
- }
-
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
-
- }
-
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- return false;
- }
-
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
-
- }
- });
-
- }
-
- private void setUpCamera() {
- cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
-
- try {
- for (String cameraId : cameraManager.getCameraIdList()) {
-
- CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
- Integer facing = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
-
- if (facing == CameraCharacteristics.LENS_FACING_BACK) {
-
- cameraID = cameraId;
-
- StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
- yuvSizes = streamConfigurationMap.getOutputSizes(ImageFormat.YUV_420_888);
-
- setUpImageReader();
- }
- }
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- private void setUpImageReader() {
-
- Size yuvSize = yuvSizes[yuvSizes.length - 6];
-
- ImageReader yuvImageReader = ImageReader.newInstance(yuvSize.getWidth(), yuvSize.getHeight(), ImageFormat.YUV_420_888, 5);
- ImageReader.OnImageAvailableListener yuvImageListener = new ImageReader.OnImageAvailableListener() {
-
- @Override
- public void onImageAvailable(ImageReader reader) {
-
- if (!readQr) {
- return;
- }
-
- Image lastImage = reader.acquireLatestImage();
- Bitmap bitmap = YUV2Bitmap(lastImage);
-
- if (bitmap != null) {
-
- Frame frame = new Frame.Builder().setBitmap(bitmap).build();
- SparseArray barcodes = barcodeDetector.detect(frame);
-
- if (barcodes.size() > 0) {
- returnResult(barcodes.valueAt(0).rawValue);
- }
- }
-
- if (lastImage != null) {
- lastImage.close();
- }
- }
- };
-
- yuvImageReader.setOnImageAvailableListener(yuvImageListener, backgroundHandler);
-
- previewSurface = new Surface(previewSurfaceTexture);
- yuvSurface = yuvImageReader.getSurface();
-
- openCamera();
- }
-
- public void openCamera() {
-
- CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
- @Override
- public void onOpened(@NonNull CameraDevice camera) {
- cameraDevice = camera;
- createCaptureSession();
- }
-
- @Override
- public void onDisconnected(@NonNull CameraDevice camera) {
-
- }
-
- @Override
- public void onError(@NonNull CameraDevice camera, int error) {
-
- }
- };
-
- try {
- if (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
- cameraManager.openCamera(cameraID, stateCallback, backgroundHandler);
- }
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- private void createCaptureSession() {
- List surfaces = Arrays.asList(previewSurface, yuvSurface);
-
- CameraCaptureSession.StateCallback captureStateCallback = new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession session) {
- cameraCaptureSession = session;
- createCaptureRequest();
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession session) {
-
- }
- };
-
- try {
- cameraDevice.createCaptureSession(surfaces, captureStateCallback, backgroundHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
-
- }
-
- private void createCaptureRequest() {
- try {
-
- CaptureRequest.Builder requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
- requestBuilder.addTarget(previewSurface);
- requestBuilder.addTarget(yuvSurface);
-
- CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
- @Override
- public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
- super.onCaptureCompleted(session, request, result);
- }
- };
-
- cameraCaptureSession.setRepeatingRequest(requestBuilder.build(), captureCallback, backgroundHandler);
-
- } catch (CameraAccessException e) {
- e.printStackTrace();
- }
- }
-
- private void openBackgroundThread() {
- backgroundThread = new HandlerThread("raw_image_available_listener_thread");
- backgroundThread.start();
- backgroundHandler = new Handler(backgroundThread.getLooper());
- }
-
- private void closeBackgroundThread() {
- backgroundThread.quitSafely();
- try {
- backgroundThread.join();
- backgroundThread = null;
- backgroundHandler = null;
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- public void closeCamera() {
- if (cameraCaptureSession != null) {
- cameraCaptureSession.close();
- cameraCaptureSession = null;
- }
-
- if (cameraDevice != null) {
- cameraDevice.close();
- cameraDevice = null;
- }
- }
-
- private void setUpBarcodeDetector() {
- barcodeDetector = new BarcodeDetector.Builder(getActivity())
- .setBarcodeFormats(Barcode.QR_CODE)
- .build();
-
- if (!barcodeDetector.isOperational()) {
- Toast.makeText(getActivity(), "Could not setup QR-Code scanner!", Toast.LENGTH_SHORT).show();
- }
- }
-
- private Bitmap YUV2Bitmap(Image image) {
-
- if (image == null) return null;
-
- int W = image.getWidth();
- int H = image.getHeight();
-
- Image.Plane Y = image.getPlanes()[0];
- Image.Plane U = image.getPlanes()[1];
- Image.Plane V = image.getPlanes()[2];
-
- int Yb = Y.getBuffer().remaining();
- int Ub = U.getBuffer().remaining();
- int Vb = V.getBuffer().remaining();
-
- byte[] data = new byte[Yb + Ub + Vb];
-
- Y.getBuffer().get(data, 0, Yb);
- V.getBuffer().get(data, Yb, Vb);
- U.getBuffer().get(data, Yb + Vb, Ub);
-
- RenderScript rs = RenderScript.create(getActivity().getApplicationContext());
-
- ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
-
- Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
- Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
-
- Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H);
- Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
-
-
- final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);
-
- in.copyFromUnchecked(data);
-
- yuvToRgbIntrinsic.setInput(in);
- yuvToRgbIntrinsic.forEach(out);
- out.copyTo(bmpout);
- image.close();
- return bmpout;
- }
-
- public void setReadQr(boolean enabled) {
- readQr = enabled;
- }
-
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/fragment/ShowQrFragment.java b/app/src/main/java/de/overview/wg/its/mispauth/fragment/ShowQrFragment.java
deleted file mode 100644
index b4aba66..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/fragment/ShowQrFragment.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package de.overview.wg.its.mispauth.fragment;
-
-import android.graphics.Point;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
-import net.glxn.qrgen.android.QRCode;
-
-public class ShowQrFragment extends Fragment {
-
- private ImageView qrImageView;
- private int screenWidth, screenHeight;
-
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_sync_show, null);
-
-// DisplayMetrics metrics = new DisplayMetrics();
-// getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
-//
-// screenWidth = (int)(metrics.widthPixels * metrics.density);
-// screenHeight = (int)(metrics.heightPixels * metrics.density);
-
-// Display display = getActivity().getWindowManager().getDefaultDisplay();
-// Point size = new Point();
-// display.getSize(size);
-// screenWidth = size.x;
-// screenHeight = size.y;
-
- screenHeight = getResources().getDisplayMetrics().heightPixels;
- screenWidth = getResources().getDisplayMetrics().widthPixels;
-
- qrImageView = v.findViewById(R.id.image_view_qr);
-
- PreferenceManager preferenceManager = PreferenceManager.Instance(getActivity());
- setQr(preferenceManager.getMyOrganisation().toJSON().toString());
-
- return v;
- }
-
- private void setQr(String msg) {
- qrImageView.setImageBitmap(QRCode.from(msg)
- .withSize(screenHeight, screenHeight)
- .bitmap());
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/fragment/SyncStartFragment.java b/app/src/main/java/de/overview/wg/its/mispauth/fragment/SyncStartFragment.java
deleted file mode 100644
index 98409e9..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/fragment/SyncStartFragment.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package de.overview.wg.its.mispauth.fragment;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RadioGroup;
-import de.overview.wg.its.mispauth.R;
-import de.overview.wg.its.mispauth.activity.SyncActivity;
-
-
-public class SyncStartFragment extends Fragment {
-
- private static final String TAG = "DEBUG";
- private RadioGroup radioGroup;
-
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_sync_start, null);
- radioGroup = v.findViewById(R.id.radioGroup);
-
- radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(RadioGroup group, int checkedId) {
- ((SyncActivity)getActivity()).setPartnerChoice(checkedId % 2);
- }
- });
-
- return v;
- }
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/fragment/UploadFragment.java b/app/src/main/java/de/overview/wg/its/mispauth/fragment/UploadFragment.java
deleted file mode 100644
index f30e64d..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/fragment/UploadFragment.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package de.overview.wg.its.mispauth.fragment;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import de.overview.wg.its.mispauth.R;
-
-public class UploadFragment extends Fragment {
-
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_sync_upload, null);
- return v;
- }
-
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/interfaces/IProcessable.java b/app/src/main/java/de/overview/wg/its/mispauth/interfaces/IProcessable.java
deleted file mode 100644
index 76d7e55..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/interfaces/IProcessable.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package de.overview.wg.its.mispauth.interfaces;
-
-public interface IProcessable {
- boolean isDone();
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/interfaces/ISyncCommunication.java b/app/src/main/java/de/overview/wg/its/mispauth/interfaces/ISyncCommunication.java
deleted file mode 100644
index 1b8efb9..0000000
--- a/app/src/main/java/de/overview/wg/its/mispauth/interfaces/ISyncCommunication.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package de.overview.wg.its.mispauth.interfaces;
-
-public interface ISyncCommunication {
- void setPartnerChoice(int choice);
- void setScannedQr(String qr);
-}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/Organisation.java b/app/src/main/java/de/overview/wg/its/mispauth/model/Organisation.java
index 50b1c98..af2d218 100644
--- a/app/src/main/java/de/overview/wg/its/mispauth/model/Organisation.java
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/Organisation.java
@@ -5,6 +5,8 @@ import org.json.JSONObject;
public class Organisation {
+ public static final String ROOT_KEY = "Organisation";
+
private static String ID_KEY = "id";
private static String NAME_KEY = "name";
private static String DATE_CREATED_KEY = "date_created";
@@ -34,48 +36,57 @@ public class Organisation {
private int createdBy;
private int userCount;
- public Organisation() {}
-
- public void fromJSON(JSONObject org) {
-
- try {
- id = org.getInt(ID_KEY);
- dateCreated = org.getString(DATE_CREATED_KEY);
- dateModified = org.getString(DATE_MODIFIED_KEY);
- name = org.getString(NAME_KEY);
- type = org.getString(TYPE_KEY);
- nationality = org.getString(NATIONALITY_KEY);
- sector = org.getString(SECTOR_KEY);
- contacts = org.getString(CONTACTS_KEY);
- description = org.getString(DESCRIPTION_KEY);
- local = org.getBoolean(LOCAL_KEY);
- uuid = org.getString(UUID_KEY);
- restrictedToDomain = org.getString(RESTRICTED_TO_DOMAIN_KEY);
- createdBy = org.getInt(CREATED_BY_KEY);
- userCount = org.getInt(USER_COUNT_KEY);
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
+ public Organisation() {
}
+
+ public Organisation(JSONObject json) throws JSONException {
+ fromJSON(json);
+ }
+
+ public void fromJSON(JSONObject org) throws JSONException {
+
+ id = org.optInt(ID_KEY, -1);
+ dateCreated = org.optString(DATE_CREATED_KEY);
+ dateModified = org.optString(DATE_MODIFIED_KEY);
+ name = org.optString(NAME_KEY);
+ type = org.optString(TYPE_KEY);
+ nationality = org.optString(NATIONALITY_KEY);
+ sector = org.optString(SECTOR_KEY);
+ contacts = org.optString(CONTACTS_KEY);
+ description = org.optString(DESCRIPTION_KEY);
+ local = org.optBoolean(LOCAL_KEY, true);
+ uuid = org.optString(UUID_KEY);
+ restrictedToDomain = org.optString(RESTRICTED_TO_DOMAIN_KEY);
+ createdBy = org.optInt(CREATED_BY_KEY, -1);
+ userCount = org.optInt(USER_COUNT_KEY);
+
+ }
+
public JSONObject toJSON() {
+ return toJSON(false);
+ }
+
+ public JSONObject toJSON(boolean minimal) {
JSONObject org = new JSONObject();
try {
- org.put(ID_KEY, id);
- org.put(NAME_KEY, name);
- org.put(DATE_CREATED_KEY, dateCreated);
- org.put(DATE_MODIFIED_KEY, dateModified);
- org.put(TYPE_KEY, type);
- org.put(NATIONALITY_KEY, nationality);
- org.put(SECTOR_KEY, sector);
- org.put(CONTACTS_KEY, contacts);
- org.put(DESCRIPTION_KEY, description);
- org.put(LOCAL_KEY, local);
- org.put(UUID_KEY, uuid);
- org.put(RESTRICTED_TO_DOMAIN_KEY, restrictedToDomain);
- org.put(CREATED_BY_KEY, createdBy);
- org.put(USER_COUNT_KEY, userCount);
+ org.putOpt(NAME_KEY, name);
+ org.putOpt(DESCRIPTION_KEY, description);
+ org.putOpt(NATIONALITY_KEY, nationality);
+ org.putOpt(SECTOR_KEY, sector);
+ org.putOpt(USER_COUNT_KEY, userCount);
+
+ if (!minimal) {
+ org.putOpt(ID_KEY, id);
+ org.putOpt(UUID_KEY, uuid);
+ org.putOpt(TYPE_KEY, type);
+ org.putOpt(CONTACTS_KEY, contacts);
+ org.putOpt(DATE_CREATED_KEY, dateCreated);
+ org.putOpt(DATE_MODIFIED_KEY, dateModified);
+ org.putOpt(LOCAL_KEY, local);
+ org.putOpt(RESTRICTED_TO_DOMAIN_KEY, restrictedToDomain);
+ org.putOpt(CREATED_BY_KEY, createdBy);
+ }
} catch (JSONException e) {
e.printStackTrace();
@@ -88,13 +99,15 @@ public class Organisation {
public void setName(String name) {
this.name = name;
}
- public String getName(){
+
+ public String getName() {
return name;
}
public String getDescription() {
return description;
}
+
public void setDescription(String description) {
this.description = description;
}
@@ -102,6 +115,7 @@ public class Organisation {
public String getSector() {
return sector;
}
+
public void setSector(String sector) {
this.sector = sector;
}
@@ -109,6 +123,7 @@ public class Organisation {
public String getNationality() {
return nationality;
}
+
public void setNationality(String nationality) {
this.nationality = nationality;
}
@@ -116,6 +131,7 @@ public class Organisation {
public int getId() {
return id;
}
+
public void setId(int id) {
this.id = id;
}
@@ -123,6 +139,7 @@ public class Organisation {
public String getDateCreated() {
return dateCreated;
}
+
public void setDateCreated(String dateCreated) {
this.dateCreated = dateCreated;
}
@@ -130,6 +147,7 @@ public class Organisation {
public String getDateModified() {
return dateModified;
}
+
public void setDateModified(String dateModified) {
this.dateModified = dateModified;
}
@@ -137,6 +155,7 @@ public class Organisation {
public String getType() {
return type;
}
+
public void setType(String type) {
this.type = type;
}
@@ -144,6 +163,7 @@ public class Organisation {
public String getContacts() {
return contacts;
}
+
public void setContacts(String contacts) {
this.contacts = contacts;
}
@@ -151,6 +171,7 @@ public class Organisation {
public boolean isLocal() {
return local;
}
+
public void setLocal(boolean local) {
this.local = local;
}
@@ -158,6 +179,7 @@ public class Organisation {
public String getUuid() {
return uuid;
}
+
public void setUuid(String uuid) {
this.uuid = uuid;
}
@@ -165,6 +187,7 @@ public class Organisation {
public String getRestrictedToDomain() {
return restrictedToDomain;
}
+
public void setRestrictedToDomain(String restrictedToDomain) {
this.restrictedToDomain = restrictedToDomain;
}
@@ -172,6 +195,7 @@ public class Organisation {
public int getCreatedBy() {
return createdBy;
}
+
public void setCreatedBy(int createdBy) {
this.createdBy = createdBy;
}
@@ -179,6 +203,7 @@ public class Organisation {
public int getUserCount() {
return userCount;
}
+
public void setUserCount(int userCount) {
this.userCount = userCount;
}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/PublicKeyQr.java b/app/src/main/java/de/overview/wg/its/mispauth/model/PublicKeyQr.java
new file mode 100644
index 0000000..358228b
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/PublicKeyQr.java
@@ -0,0 +1,61 @@
+package de.overview.wg.its.mispauth.model;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class PublicKeyQr {
+
+ private static final String KEY_ORG = "org";
+ private static final String KEY_USER = "user";
+ private static final String KEY_KEY = "key";
+
+ private String organisation, user, key;
+
+ public PublicKeyQr(JSONObject qr) throws JSONException {
+ organisation = qr.getString(KEY_ORG);
+ user = qr.getString(KEY_USER);
+ key = qr.getString(KEY_KEY);
+ }
+
+ public PublicKeyQr(String qr) throws JSONException{
+ JSONObject json = new JSONObject(qr);
+
+ organisation = json.getString(KEY_ORG);
+ user = json.getString(KEY_USER);
+ key = json.getString(KEY_KEY);
+ }
+
+ public PublicKeyQr(String organisation, String user, String key) {
+ this.organisation = organisation;
+ this.user = user;
+ this.key = key;
+ }
+
+ public JSONObject toJSON() {
+ try {
+ JSONObject json = new JSONObject();
+
+ json.put(KEY_ORG, organisation);
+ json.put(KEY_USER, user);
+ json.put(KEY_KEY, key);
+
+ return json;
+
+ } catch (JSONException e) {
+
+ return null;
+ }
+ }
+
+ public String getOrganisation() {
+ return organisation;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public String getKey() {
+ return key;
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/Server.java b/app/src/main/java/de/overview/wg/its/mispauth/model/Server.java
index 32077ca..785e505 100644
--- a/app/src/main/java/de/overview/wg/its/mispauth/model/Server.java
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/Server.java
@@ -1,5 +1,105 @@
package de.overview.wg.its.mispauth.model;
+import org.json.JSONException;
+import org.json.JSONObject;
+
public class Server {
+ public static final String ROOT_KEY = "Server";
+
+ private static final String URL_KEY = "url";
+ private static final String NAME_KEY = "name";
+ private static final String REMOTE_ORG_ID_KEY = "remote_org_id";
+ private static final String AUTHKEY_KEY = "authkey";
+ private static final String PUSH_KEY = "push";
+ private static final String PULL_KEY = "pull";
+
+ private String url;
+ private String name;
+ private int remoteOrgId;
+ private String authkey;
+ private boolean push, pull;
+
+ public Server() { }
+ public Server(JSONObject json) throws JSONException {
+ fromJSON(json);
+ }
+
+ public void fromJSON(JSONObject server) throws JSONException {
+ url = server.optString(URL_KEY);
+ name = server.optString(NAME_KEY);
+ remoteOrgId = server.optInt(REMOTE_ORG_ID_KEY, -1);
+ authkey = server.optString(AUTHKEY_KEY);
+ push = server.optBoolean(PUSH_KEY, false);
+ pull = server.optBoolean(PULL_KEY, false);
+ }
+
+ public JSONObject toJSON() {
+ return toJSON(false);
+ }
+ public JSONObject toJSON(boolean minimal) {
+
+ JSONObject jsonObject = new JSONObject();
+
+ try {
+ jsonObject.putOpt(URL_KEY, url);
+ jsonObject.putOpt(NAME_KEY, name);
+ jsonObject.putOpt(AUTHKEY_KEY, authkey);
+
+ if (!minimal) {
+ jsonObject.putOpt(REMOTE_ORG_ID_KEY, remoteOrgId);
+ jsonObject.putOpt(PUSH_KEY, push);
+ jsonObject.putOpt(PULL_KEY, pull);
+ }
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ return jsonObject;
+ }
+
+
+ public String getUrl() {
+ return url;
+ }
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getRemoteOrgId() {
+ return remoteOrgId;
+ }
+ public void setRemoteOrgId(int remoteOrgId) {
+ this.remoteOrgId = remoteOrgId;
+ }
+
+ public String getAuthkey() {
+ return authkey;
+ }
+ public void setAuthkey(String authkey) {
+ this.authkey = authkey;
+ }
+
+ public boolean isPush() {
+ return push;
+ }
+ public void setPush(boolean push) {
+ this.push = push;
+ }
+
+ public boolean isPull() {
+ return pull;
+ }
+ public void setPull(boolean pull) {
+ this.pull = pull;
+ }
+
}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/SyncInformationQr.java b/app/src/main/java/de/overview/wg/its/mispauth/model/SyncInformationQr.java
new file mode 100644
index 0000000..7dbcdd3
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/SyncInformationQr.java
@@ -0,0 +1,50 @@
+package de.overview.wg.its.mispauth.model;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+public class SyncInformationQr {
+
+ private Organisation organisation;
+ private Server server;
+ private User user;
+
+ public SyncInformationQr(Organisation organisation, Server server, User user) {
+ this.organisation = organisation;
+ this.server = server;
+ this.user = user;
+ }
+ public SyncInformationQr(String stringArray) throws JSONException {
+ fromJSON(new JSONArray(stringArray));
+ }
+
+ private void fromJSON(JSONArray array) throws JSONException {
+ int length = array.length();
+
+ if (length == 3) {
+ organisation = new Organisation(array.getJSONObject(0));
+ server = new Server(array.getJSONObject(1));
+ user = new User(array.getJSONObject(2));
+ }
+ }
+
+ public JSONArray toJSON() {
+ JSONArray array = new JSONArray();
+
+ array.put(organisation.toJSON(true));
+ array.put(server.toJSON(true));
+ array.put(user.toJSON(true));
+
+ return array;
+ }
+
+ public Organisation getOrganisation() {
+ return organisation;
+ }
+ public Server getServer() {
+ return server;
+ }
+ public User getUser() {
+ return user;
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/SyncedPartner.java b/app/src/main/java/de/overview/wg/its/mispauth/model/SyncedPartner.java
new file mode 100644
index 0000000..6cd88ce
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/SyncedPartner.java
@@ -0,0 +1,48 @@
+package de.overview.wg.its.mispauth.model;
+
+import android.annotation.SuppressLint;
+
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+
+public class SyncedPartner {
+
+ @SuppressLint("SimpleDateFormat")
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
+
+ private String name;
+ private String url;
+ private String syncDate;
+
+ public SyncedPartner(String name, String url) {
+ this.name = name;
+ this.url = url;
+ }
+
+ public void generateTimeStamp() {
+ syncDate = dateFormat.format(new Timestamp(System.currentTimeMillis()));
+ }
+
+ // GETTER & SETTER
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getSyncDate() {
+ return syncDate;
+ }
+ public void setSyncDate(String syncDate) {
+ this.syncDate = syncDate;
+ }
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/UploadState.java b/app/src/main/java/de/overview/wg/its/mispauth/model/UploadState.java
new file mode 100644
index 0000000..6eb71c4
--- /dev/null
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/UploadState.java
@@ -0,0 +1,41 @@
+package de.overview.wg.its.mispauth.model;
+
+public class UploadState {
+
+ public enum State {
+ PENDING,
+ IN_PROGRESS,
+ DONE,
+ ERROR
+ }
+ private State currentState = State.PENDING;
+ private String title, error;
+
+
+ public UploadState(String title) {
+ this.title = title;
+ }
+
+
+ public String getTitle() {
+ return title;
+ }
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getError() {
+ return error;
+ }
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public State getCurrentState() {
+ return currentState;
+ }
+ public void setCurrentState(State currentState) {
+ this.currentState = currentState;
+ }
+
+}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/model/User.java b/app/src/main/java/de/overview/wg/its/mispauth/model/User.java
index bb06663..382ba16 100644
--- a/app/src/main/java/de/overview/wg/its/mispauth/model/User.java
+++ b/app/src/main/java/de/overview/wg/its/mispauth/model/User.java
@@ -5,6 +5,18 @@ import org.json.JSONObject;
public class User {
+ // todo: must be configable? Roles can be edited on instance
+ public interface RoleId {
+ int ADMIN = 1;
+ int ORG_ADMIN = 2;
+ int USER = 3;
+ int PUBLISHER = 4;
+ int SYNC_USER = 5;
+ int READ_ONLY = 6;
+ }
+
+ public static final String ROOT_KEY = "User";
+
private static String ID_KEY = "id";
private static String PASSWORD_KEY = "password";
private static String ORG_ID_KEY = "org_id";
@@ -51,79 +63,85 @@ public class User {
private String dateCreated;
private String dateModified;
- public User() {}
-
- public void fromJSON(JSONObject user) {
- try {
-
- id = user.getInt(ID_KEY);
- password = user.getString(PASSWORD_KEY);
- orgId = user.getInt(ORG_ID_KEY);
- email = user.getString(EMAIL_KEY);
- autoAlert = user.getBoolean(AUTOALERT_KEY);
- authkey = user.getString(AUTHKEY_KEY);
- invitedBy = user.getInt(INVITED_BY_KEY);
- gpgKey = user.getString(GPGKEY_KEY);
- certifPublic = user.getString(CERTIF_PUBLIC);
- nidsSid = user.getInt(NIDS_SID);
- termsAccepted = user.getBoolean(TERMS_ACCEPTED_KEY);
- newsRead = user.getInt(NEWSREAD_KEY);
- roleId = user.getInt(ROLE_ID_KEY);
- changePw = user.getString(CHANGE_PW_KEY);
- contactAlert = user.getBoolean(CONTACT_ALERT_KEY);
- disabled = user.getBoolean(DISABLED_KEY);
- expiration = user.getString(EXPIRATION_KEY);
- currentLogin = user.getString(CURRENT_LOGIN_KEY);
- lastLogin = user.getString(LAST_LOGIN_KEY);
- forceLogout = user.getBoolean(FORCE_LOGOUT_KEY);
- dateCreated = user.getString(DATE_CREATED_KEY);
- dateModified = user.getString(DATE_MODIFIED_KEY);
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
-
+ public User() {
+ }
+ public User(JSONObject user) throws JSONException {
+ fromJSON(user);
}
+ public void fromJSON(JSONObject user) throws JSONException {
+
+ id = user.optInt(ID_KEY, -1);
+ password = user.optString(PASSWORD_KEY);
+ orgId = user.optInt(ORG_ID_KEY, -1);
+ email = user.optString(EMAIL_KEY);
+ autoAlert = user.optBoolean(AUTOALERT_KEY);
+ authkey = user.optString(AUTHKEY_KEY);
+ invitedBy = user.optInt(INVITED_BY_KEY, -1);
+ gpgKey = user.optString(GPGKEY_KEY);
+ certifPublic = user.optString(CERTIF_PUBLIC);
+ nidsSid = user.optInt(NIDS_SID);
+ termsAccepted = user.optBoolean(TERMS_ACCEPTED_KEY, false);
+ newsRead = user.optInt(NEWSREAD_KEY);
+ roleId = user.optInt(ROLE_ID_KEY, -1);
+ changePw = user.optString(CHANGE_PW_KEY);
+ contactAlert = user.optBoolean(CONTACT_ALERT_KEY, true);
+ disabled = user.optBoolean(DISABLED_KEY, false);
+ expiration = user.optString(EXPIRATION_KEY);
+ currentLogin = user.optString(CURRENT_LOGIN_KEY);
+ lastLogin = user.optString(LAST_LOGIN_KEY);
+ forceLogout = user.optBoolean(FORCE_LOGOUT_KEY);
+ dateCreated = user.optString(DATE_CREATED_KEY);
+ dateModified = user.optString(DATE_MODIFIED_KEY);
+
+ }
public JSONObject toJSON() {
+ return toJSON(false);
+ }
+ public JSONObject toJSON(boolean forSyncQR) {
JSONObject user = new JSONObject();
try {
- user.put(ID_KEY, id);
- user.put(PASSWORD_KEY, password);
- user.put(ORG_ID_KEY, orgId);
- user.put(EMAIL_KEY, email);
- user.put(AUTOALERT_KEY, autoAlert);
- user.put(AUTHKEY_KEY, authkey);
- user.put(INVITED_BY_KEY, invitedBy);
- user.put(GPGKEY_KEY, gpgKey);
- user.put(CERTIF_PUBLIC, certifPublic);
- user.put(NIDS_SID, nidsSid);
- user.put(TERMS_ACCEPTED_KEY, termsAccepted);
- user.put(NEWSREAD_KEY, newsRead);
- user.put(ROLE_ID_KEY, roleId);
- user.put(CHANGE_PW_KEY, changePw);
- user.put(CONTACT_ALERT_KEY, contactAlert);
- user.put(DISABLED_KEY, disabled);
- user.put(EXPIRATION_KEY, expiration);
- user.put(CURRENT_LOGIN_KEY, currentLogin);
- user.put(LAST_LOGIN_KEY, lastLogin);
- user.put(FORCE_LOGOUT_KEY, forceLogout);
- user.put(DATE_CREATED_KEY, dateCreated);
- user.put(DATE_MODIFIED_KEY, dateModified);
+ user.putOpt(EMAIL_KEY, email);
+
+ if (!forSyncQR) {
+
+ user.putOpt(ID_KEY, id);
+ user.putOpt(ORG_ID_KEY, orgId);
+ user.putOpt(AUTHKEY_KEY, authkey);
+ user.putOpt(ROLE_ID_KEY, roleId);
+ user.putOpt(PASSWORD_KEY, password);
+ user.putOpt(CHANGE_PW_KEY, changePw);
+ user.putOpt(TERMS_ACCEPTED_KEY, termsAccepted);
+ user.putOpt(CERTIF_PUBLIC, certifPublic);
+ user.putOpt(GPGKEY_KEY, gpgKey);
+ user.putOpt(AUTOALERT_KEY, autoAlert);
+ user.putOpt(INVITED_BY_KEY, invitedBy);
+ user.putOpt(NIDS_SID, nidsSid);
+ user.putOpt(NEWSREAD_KEY, newsRead);
+ user.putOpt(CONTACT_ALERT_KEY, contactAlert);
+ user.putOpt(DISABLED_KEY, disabled);
+ user.putOpt(EXPIRATION_KEY, expiration);
+ user.putOpt(CURRENT_LOGIN_KEY, currentLogin);
+ user.putOpt(LAST_LOGIN_KEY, lastLogin);
+ user.putOpt(FORCE_LOGOUT_KEY, forceLogout);
+ user.putOpt(DATE_CREATED_KEY, dateCreated);
+ user.putOpt(DATE_MODIFIED_KEY, dateModified);
+
+ }
} catch (JSONException e) {
e.printStackTrace();
}
- return user;
+ return user;
}
+
public int getId() {
return id;
}
-
public void setId(int id) {
this.id = id;
}
@@ -131,7 +149,6 @@ public class User {
public String getPassword() {
return password;
}
-
public void setPassword(String password) {
this.password = password;
}
@@ -139,7 +156,6 @@ public class User {
public int getOrgId() {
return orgId;
}
-
public void setOrgId(int orgId) {
this.orgId = orgId;
}
@@ -147,7 +163,6 @@ public class User {
public String getEmail() {
return email;
}
-
public void setEmail(String email) {
this.email = email;
}
@@ -155,7 +170,6 @@ public class User {
public boolean isAutoAlert() {
return autoAlert;
}
-
public void setAutoAlert(boolean autoAlert) {
this.autoAlert = autoAlert;
}
@@ -163,7 +177,6 @@ public class User {
public String getAuthkey() {
return authkey;
}
-
public void setAuthkey(String authkey) {
this.authkey = authkey;
}
@@ -171,7 +184,6 @@ public class User {
public int getInvitedBy() {
return invitedBy;
}
-
public void setInvitedBy(int invitedBy) {
this.invitedBy = invitedBy;
}
@@ -179,7 +191,6 @@ public class User {
public String getGpgKey() {
return gpgKey;
}
-
public void setGpgKey(String gpgKey) {
this.gpgKey = gpgKey;
}
@@ -187,7 +198,6 @@ public class User {
public String getCertifPublic() {
return certifPublic;
}
-
public void setCertifPublic(String certifPublic) {
this.certifPublic = certifPublic;
}
@@ -195,7 +205,6 @@ public class User {
public int getNidsSid() {
return nidsSid;
}
-
public void setNidsSid(int nidsSid) {
this.nidsSid = nidsSid;
}
@@ -203,7 +212,6 @@ public class User {
public boolean isTermsAccepted() {
return termsAccepted;
}
-
public void setTermsAccepted(boolean termsAccepted) {
this.termsAccepted = termsAccepted;
}
@@ -211,7 +219,6 @@ public class User {
public int getNewsRead() {
return newsRead;
}
-
public void setNewsRead(int newsRead) {
this.newsRead = newsRead;
}
@@ -219,7 +226,6 @@ public class User {
public int getRoleId() {
return roleId;
}
-
public void setRoleId(int roleId) {
this.roleId = roleId;
}
@@ -227,7 +233,6 @@ public class User {
public String getChangePw() {
return changePw;
}
-
public void setChangePw(String changePw) {
this.changePw = changePw;
}
@@ -235,7 +240,6 @@ public class User {
public boolean isContactAlert() {
return contactAlert;
}
-
public void setContactAlert(boolean contactAlert) {
this.contactAlert = contactAlert;
}
@@ -243,7 +247,6 @@ public class User {
public boolean isDisabled() {
return disabled;
}
-
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
@@ -251,7 +254,6 @@ public class User {
public String getExpiration() {
return expiration;
}
-
public void setExpiration(String expiration) {
this.expiration = expiration;
}
@@ -259,7 +261,6 @@ public class User {
public String getCurrentLogin() {
return currentLogin;
}
-
public void setCurrentLogin(String currentLogin) {
this.currentLogin = currentLogin;
}
@@ -267,7 +268,6 @@ public class User {
public String getLastLogin() {
return lastLogin;
}
-
public void setLastLogin(String lastLogin) {
this.lastLogin = lastLogin;
}
@@ -275,7 +275,6 @@ public class User {
public boolean isForceLogout() {
return forceLogout;
}
-
public void setForceLogout(boolean forceLogout) {
this.forceLogout = forceLogout;
}
@@ -283,7 +282,6 @@ public class User {
public String getDateCreated() {
return dateCreated;
}
-
public void setDateCreated(String dateCreated) {
this.dateCreated = dateCreated;
}
@@ -291,7 +289,6 @@ public class User {
public String getDateModified() {
return dateModified;
}
-
public void setDateModified(String dateModified) {
this.dateModified = dateModified;
}
diff --git a/app/src/main/java/de/overview/wg/its/mispauth/network/MispRequest.java b/app/src/main/java/de/overview/wg/its/mispauth/network/MispRequest.java
index 81c4a5b..9f3fa72 100644
--- a/app/src/main/java/de/overview/wg/its/mispauth/network/MispRequest.java
+++ b/app/src/main/java/de/overview/wg/its/mispauth/network/MispRequest.java
@@ -7,16 +7,31 @@ import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
-import com.android.volley.toolbox.JsonArrayRequest;
+import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
+import de.overview.wg.its.mispauth.R;
import de.overview.wg.its.mispauth.auxiliary.PreferenceManager;
import de.overview.wg.its.mispauth.auxiliary.ReadableError;
import de.overview.wg.its.mispauth.model.Organisation;
+import de.overview.wg.its.mispauth.model.Server;
+import de.overview.wg.its.mispauth.model.User;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import javax.net.ssl.*;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
@@ -38,6 +53,7 @@ public class MispRequest {
private MispRequest(Context context) {
requestQueue = Volley.newRequestQueue(context);
preferenceManager = PreferenceManager.Instance(context);
+
loadSavedCredentials();
}
@@ -56,13 +72,10 @@ public class MispRequest {
@Override
public void onResponse(JSONObject response) {
try {
- callback.onResult(response.getJSONObject("Organisation"));
- return;
+ callback.onResult(response.getJSONObject(Organisation.ROOT_KEY));
} catch (JSONException e) {
e.printStackTrace();
}
-
- callback.onResult(response);
}
};
@@ -88,14 +101,14 @@ public class MispRequest {
*
* @param callback return user associated with this API-Key
*/
- public void myUserInformation(final UserCallback callback) {
+ public void getMyUser(final UserCallback callback) {
Response.Listener listener = new Response.Listener() {
@Override
public void onResponse(JSONObject response) {
try {
- callback.onResult(response.getJSONObject("User"));
+ callback.onResult(response.getJSONObject(User.ROOT_KEY));
return;
} catch (JSONException e) {
e.printStackTrace();
@@ -114,7 +127,7 @@ public class MispRequest {
};
if (serverUrl.isEmpty() || apiKey.isEmpty()) {
- Log.e(TAG, "myUserInformation: server or api key is empty!");
+ Log.e(TAG, "getMyUser: server or api key is empty!");
return;
}
@@ -137,13 +150,10 @@ public class MispRequest {
@Override
public void onResponse(JSONObject response) {
try {
- callback.onResult(response.getJSONObject("Organisation"));
- return;
+ callback.onResult(response.getJSONObject(Organisation.ROOT_KEY));
} catch (JSONException e) {
e.printStackTrace();
}
-
- callback.onResult(response);
}
};
@@ -204,6 +214,73 @@ public class MispRequest {
requestQueue.add(r);
}
+ public void addUser(User user, final UserCallback callback) {
+ Response.Listener listener = new Response.Listener() {
+ @Override
+ public void onResponse(JSONObject response) {
+ try {
+ callback.onResult(response.getJSONObject(User.ROOT_KEY));
+ return;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ callback.onResult(response);
+ }
+ };
+
+ Response.ErrorListener errorListener = new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ callback.onError(error);
+ }
+ };
+
+ Request r = objectRequest(
+ Request.Method.POST,
+ serverUrl + "/admin/users/add",
+ user.toJSON(),
+ listener,
+ errorListener
+ );
+
+ requestQueue.add(r);
+ }
+
+ public void addServer(Server server, final ServerCallback callback) {
+ Response.Listener listener = new Response.Listener() {
+ @Override
+ public void onResponse(JSONObject response) {
+ try {
+ callback.onResult(response.getJSONObject(Server.ROOT_KEY));
+ return;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ callback.onResult(response);
+ }
+ };
+
+ Response.ErrorListener errorListener = new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ callback.onError(error);
+ }
+ };
+
+ Request r = objectRequest(
+ Request.Method.POST,
+ serverUrl + "/servers/add",
+ server.toJSON(),
+ listener,
+ errorListener
+ );
+
+ requestQueue.add(r);
+ }
+
+
private JsonArrayRequestWithJsonObject arrayRequestWithJsonObject(int method, String url,
@Nullable JSONObject body,
Response.Listener listener,
@@ -247,6 +324,72 @@ public class MispRequest {
this.apiKey = apiKey;
}
+// private SSLSocketFactory getSocketFactory(Context context) {
+//
+// CertificateFactory cf = null;
+// try {
+// cf = CertificateFactory.getInstance("X.509");
+// InputStream caInput = context.getResources().openRawResource(R.raw.server);
+// Certificate ca;
+// try {
+// ca = cf.generateCertificate(caInput);
+// Log.e("CERT", "ca=" + ((X509Certificate) ca).getSubjectDN());
+// } finally {
+// caInput.close();
+// }
+//
+//
+// String keyStoreType = KeyStore.getDefaultType();
+// KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+// keyStore.load(null, null);
+// keyStore.setCertificateEntry("ca", ca);
+//
+//
+// String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+// TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
+// tmf.init(keyStore);
+//
+//
+// HostnameVerifier hostnameVerifier = new HostnameVerifier() {
+// @Override
+// public boolean verify(String hostname, SSLSession session) {
+//
+// Log.e("CipherUsed", session.getCipherSuite());
+// return hostname.compareTo("192.168.1.10")==0; //The Hostname of your server
+//
+// }
+// };
+//
+//
+// HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
+// SSLContext context = null;
+// context = SSLContext.getInstance("TLS");
+//
+// context.init(null, tmf.getTrustManagers(), null);
+// HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
+//
+// SSLSocketFactory sf = context.getSocketFactory();
+//
+//
+// return sf;
+//
+// } catch (CertificateException e) {
+// e.printStackTrace();
+// } catch (NoSuchAlgorithmException e) {
+// e.printStackTrace();
+// } catch (KeyStoreException e) {
+// e.printStackTrace();
+// } catch (FileNotFoundException e) {
+// e.printStackTrace();
+// } catch (IOException e) {
+// e.printStackTrace();
+// } catch (KeyManagementException e) {
+// e.printStackTrace();
+// }
+//
+// return null;
+// }
+
public static MispRequest Instance(Context context) {
if (instance == null) {
instance = new MispRequest(context);
@@ -264,12 +407,12 @@ public class MispRequest {
void onError(VolleyError volleyError);
}
public interface UserCallback {
- void onResult(JSONObject myOrganisationInformation);
+ void onResult(JSONObject userInformation);
void onError(VolleyError volleyError);
}
public interface ServerCallback {
- void onResult(JSONObject servers);
+ void onResult(JSONObject server);
void onError(VolleyError volleyError);
}
}
diff --git a/app/src/main/res/anim/enter_from_left.xml b/app/src/main/res/anim/enter_from_left.xml
deleted file mode 100644
index eb7fb78..0000000
--- a/app/src/main/res/anim/enter_from_left.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/anim/enter_from_right.xml b/app/src/main/res/anim/enter_from_right.xml
deleted file mode 100644
index 0c7045c..0000000
--- a/app/src/main/res/anim/enter_from_right.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/anim/exit_to_left.xml b/app/src/main/res/anim/exit_to_left.xml
deleted file mode 100644
index a9c41a6..0000000
--- a/app/src/main/res/anim/exit_to_left.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/anim/exit_to_right.xml b/app/src/main/res/anim/exit_to_right.xml
deleted file mode 100644
index 7ef31a6..0000000
--- a/app/src/main/res/anim/exit_to_right.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/anim/slide_down.xml b/app/src/main/res/anim/slide_down.xml
new file mode 100644
index 0000000..ad40deb
--- /dev/null
+++ b/app/src/main/res/anim/slide_down.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/slide_up.xml b/app/src/main/res/anim/slide_up.xml
new file mode 100644
index 0000000..a731689
--- /dev/null
+++ b/app/src/main/res/anim/slide_up.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/animator/fade_in.xml b/app/src/main/res/animator/fade_in.xml
deleted file mode 100644
index 2865a0c..0000000
--- a/app/src/main/res/animator/fade_in.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
index c7bd21d..789e157 100644
--- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -1,34 +1,34 @@
-
-
-
-
-
-
-
-
-
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportHeight="108"
+ android:viewportWidth="108">
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/background_rounded_main.xml b/app/src/main/res/drawable/background_rounded_main.xml
deleted file mode 100644
index f7c1e47..0000000
--- a/app/src/main/res/drawable/background_rounded_main.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_add_white.xml b/app/src/main/res/drawable/ic_add_white.xml
deleted file mode 100644
index e3979cd..0000000
--- a/app/src/main/res/drawable/ic_add_white.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_arrow_back_white.xml b/app/src/main/res/drawable/ic_arrow_back_white.xml
deleted file mode 100644
index 71d5bbd..0000000
--- a/app/src/main/res/drawable/ic_arrow_back_white.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml
deleted file mode 100644
index 17aca2a..0000000
--- a/app/src/main/res/drawable/ic_check.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_cloud_download_white.xml b/app/src/main/res/drawable/ic_cloud_download_white.xml
deleted file mode 100644
index 0feb270..0000000
--- a/app/src/main/res/drawable/ic_cloud_download_white.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_edit_white_24dp.xml b/app/src/main/res/drawable/ic_edit_white_24dp.xml
deleted file mode 100644
index 46462b5..0000000
--- a/app/src/main/res/drawable/ic_edit_white_24dp.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_flag_white_24dp.xml b/app/src/main/res/drawable/ic_flag_white_24dp.xml
deleted file mode 100644
index f2e075a..0000000
--- a/app/src/main/res/drawable/ic_flag_white_24dp.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_info_white.xml b/app/src/main/res/drawable/ic_info_white.xml
deleted file mode 100644
index 7be0147..0000000
--- a/app/src/main/res/drawable/ic_info_white.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index d5fccc5..1fa43f1 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,170 +1,74 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_perm_contact_calendar_white_24dp.xml b/app/src/main/res/drawable/ic_perm_contact_calendar_white_24dp.xml
deleted file mode 100644
index b07fbed..0000000
--- a/app/src/main/res/drawable/ic_perm_contact_calendar_white_24dp.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_qr_aim.xml b/app/src/main/res/drawable/ic_qr_aim.xml
deleted file mode 100644
index 3a353b0..0000000
--- a/app/src/main/res/drawable/ic_qr_aim.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_sector.xml b/app/src/main/res/drawable/ic_sector.xml
deleted file mode 100644
index 7b7f112..0000000
--- a/app/src/main/res/drawable/ic_sector.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_settings_white.xml b/app/src/main/res/drawable/ic_settings_white.xml
deleted file mode 100644
index 79af3ab..0000000
--- a/app/src/main/res/drawable/ic_settings_white.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_sync_alpha.xml b/app/src/main/res/drawable/ic_sync_alpha.xml
deleted file mode 100644
index 65dac7d..0000000
--- a/app/src/main/res/drawable/ic_sync_alpha.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_sync_white.xml b/app/src/main/res/drawable/ic_sync_white.xml
deleted file mode 100644
index 7ae478f..0000000
--- a/app/src/main/res/drawable/ic_sync_white.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/icon_add.xml b/app/src/main/res/drawable/icon_add.xml
new file mode 100644
index 0000000..0258249
--- /dev/null
+++ b/app/src/main/res/drawable/icon_add.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_check.xml b/app/src/main/res/drawable/icon_check.xml
new file mode 100644
index 0000000..459aef9
--- /dev/null
+++ b/app/src/main/res/drawable/icon_check.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_close.xml b/app/src/main/res/drawable/icon_close.xml
new file mode 100644
index 0000000..ede4b71
--- /dev/null
+++ b/app/src/main/res/drawable/icon_close.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_cloud_download.xml b/app/src/main/res/drawable/icon_cloud_download.xml
new file mode 100644
index 0000000..261c312
--- /dev/null
+++ b/app/src/main/res/drawable/icon_cloud_download.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_cloud_upload.xml b/app/src/main/res/drawable/icon_cloud_upload.xml
new file mode 100644
index 0000000..7d0637d
--- /dev/null
+++ b/app/src/main/res/drawable/icon_cloud_upload.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_contact.xml b/app/src/main/res/drawable/icon_contact.xml
new file mode 100644
index 0000000..0d6b3bb
--- /dev/null
+++ b/app/src/main/res/drawable/icon_contact.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_forward.xml b/app/src/main/res/drawable/icon_forward.xml
new file mode 100644
index 0000000..cf9e208
--- /dev/null
+++ b/app/src/main/res/drawable/icon_forward.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_hour_glass.xml b/app/src/main/res/drawable/icon_hour_glass.xml
new file mode 100644
index 0000000..fa7abc6
--- /dev/null
+++ b/app/src/main/res/drawable/icon_hour_glass.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_key.xml b/app/src/main/res/drawable/icon_key.xml
new file mode 100644
index 0000000..2eddd16
--- /dev/null
+++ b/app/src/main/res/drawable/icon_key.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_round_check.xml b/app/src/main/res/drawable/icon_round_check.xml
new file mode 100644
index 0000000..529c91e
--- /dev/null
+++ b/app/src/main/res/drawable/icon_round_check.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/icon_round_error.xml b/app/src/main/res/drawable/icon_round_error.xml
new file mode 100644
index 0000000..cb3b30a
--- /dev/null
+++ b/app/src/main/res/drawable/icon_round_error.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_settings.xml b/app/src/main/res/drawable/icon_settings.xml
new file mode 100644
index 0000000..ace746c
--- /dev/null
+++ b/app/src/main/res/drawable/icon_settings.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/rounded_square.xml b/app/src/main/res/drawable/rounded_square.xml
new file mode 100644
index 0000000..f7f114d
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_square.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/tab_indicator_default.xml b/app/src/main/res/drawable/tab_indicator_default.xml
deleted file mode 100644
index 60ae032..0000000
--- a/app/src/main/res/drawable/tab_indicator_default.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- -
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/tab_indicator_selected.xml b/app/src/main/res/drawable/tab_indicator_selected.xml
deleted file mode 100644
index f4ea196..0000000
--- a/app/src/main/res/drawable/tab_indicator_selected.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/tab_selector.xml b/app/src/main/res/drawable/tab_selector.xml
deleted file mode 100644
index 95bfb40..0000000
--- a/app/src/main/res/drawable/tab_selector.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_credentials.xml b/app/src/main/res/layout/activity_credentials.xml
new file mode 100644
index 0000000..4ce7db7
--- /dev/null
+++ b/app/src/main/res/layout/activity_credentials.xml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index c446141..7feec8d 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,92 +1,61 @@
+
+
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
+
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+
- tools:context=".activity.SettingsActivity"
- android:background="@color/colorPrimary">
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/activity_public_key_exchange.xml b/app/src/main/res/layout/activity_public_key_exchange.xml
new file mode 100644
index 0000000..397d152
--- /dev/null
+++ b/app/src/main/res/layout/activity_public_key_exchange.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
deleted file mode 100644
index aa439e7..0000000
--- a/app/src/main/res/layout/activity_settings.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_sync.xml b/app/src/main/res/layout/activity_sync.xml
deleted file mode 100644
index 8b74dcc..0000000
--- a/app/src/main/res/layout/activity_sync.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_upload.xml b/app/src/main/res/layout/activity_upload.xml
new file mode 100644
index 0000000..0753239
--- /dev/null
+++ b/app/src/main/res/layout/activity_upload.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_public_key.xml b/app/src/main/res/layout/dialog_public_key.xml
new file mode 100644
index 0000000..54122d8
--- /dev/null
+++ b/app/src/main/res/layout/dialog_public_key.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_save_authkey.xml b/app/src/main/res/layout/dialog_save_authkey.xml
new file mode 100644
index 0000000..fd9e56f
--- /dev/null
+++ b/app/src/main/res/layout/dialog_save_authkey.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_select_delete_data.xml b/app/src/main/res/layout/dialog_select_delete_data.xml
new file mode 100644
index 0000000..82c7388
--- /dev/null
+++ b/app/src/main/res/layout/dialog_select_delete_data.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_sync_info.xml b/app/src/main/res/layout/dialog_sync_info.xml
new file mode 100644
index 0000000..133dad2
--- /dev/null
+++ b/app/src/main/res/layout/dialog_sync_info.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sync_show.xml b/app/src/main/res/layout/fragment_camera.xml
similarity index 66%
rename from app/src/main/res/layout/fragment_sync_show.xml
rename to app/src/main/res/layout/fragment_camera.xml
index 40af6a0..cbed397 100644
--- a/app/src/main/res/layout/fragment_sync_show.xml
+++ b/app/src/main/res/layout/fragment_camera.xml
@@ -1,22 +1,18 @@
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_generate_keys.xml b/app/src/main/res/layout/fragment_generate_keys.xml
new file mode 100644
index 0000000..7fd8ee3
--- /dev/null
+++ b/app/src/main/res/layout/fragment_generate_keys.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_review_qr.xml b/app/src/main/res/layout/fragment_review_qr.xml
deleted file mode 100644
index 362ed28..0000000
--- a/app/src/main/res/layout/fragment_review_qr.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sync_scan.xml b/app/src/main/res/layout/fragment_sync_scan.xml
deleted file mode 100644
index 607b006..0000000
--- a/app/src/main/res/layout/fragment_sync_scan.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sync_start.xml b/app/src/main/res/layout/fragment_sync_start.xml
deleted file mode 100644
index 69628e6..0000000
--- a/app/src/main/res/layout/fragment_sync_start.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sync_upload.xml b/app/src/main/res/layout/fragment_sync_upload.xml
deleted file mode 100644
index 9d5bfad..0000000
--- a/app/src/main/res/layout/fragment_sync_upload.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/row_synced_organisation.xml b/app/src/main/res/layout/row_synced_organisation.xml
new file mode 100644
index 0000000..c0cddb5
--- /dev/null
+++ b/app/src/main/res/layout/row_synced_organisation.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/row_upload_state.xml b/app/src/main/res/layout/row_upload_state.xml
new file mode 100644
index 0000000..27c7ced
--- /dev/null
+++ b/app/src/main/res/layout/row_upload_state.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/view_holder_ext_org.xml b/app/src/main/res/layout/view_holder_ext_org.xml
deleted file mode 100644
index b9d507a..0000000
--- a/app/src/main/res/layout/view_holder_ext_org.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_holder_organisation.xml b/app/src/main/res/layout/view_organisation.xml
similarity index 98%
rename from app/src/main/res/layout/view_holder_organisation.xml
rename to app/src/main/res/layout/view_organisation.xml
index b975fa5..2564feb 100644
--- a/app/src/main/res/layout/view_holder_organisation.xml
+++ b/app/src/main/res/layout/view_organisation.xml
@@ -1,5 +1,6 @@
-
diff --git a/app/src/main/res/menu/menu_credentials.xml b/app/src/main/res/menu/menu_credentials.xml
new file mode 100644
index 0000000..6eaa8cf
--- /dev/null
+++ b/app/src/main/res/menu/menu_credentials.xml
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index 3f371e1..f6b42ae 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -1,12 +1,16 @@
-