package com.roly.nfc.crypto.ui.activity;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import android.app.PendingIntent;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.widget.EditText;
import android.widget.Toast;
import com.googlecode.androidannotations.annotations.AfterViews;
import com.googlecode.androidannotations.annotations.Background;
import com.googlecode.androidannotations.annotations.EActivity;
import com.googlecode.androidannotations.annotations.OptionsItem;
import com.googlecode.androidannotations.annotations.OptionsMenu;
import com.googlecode.androidannotations.annotations.UiThread;
import com.googlecode.androidannotations.annotations.ViewById;
import com.roly.nfc.crypto.R;
import com.roly.nfc.crypto.data.NoteDatabase;
import com.roly.nfc.crypto.data.NoteProvider;
import com.roly.nfc.crypto.ui.fragment.KeyPickerDialogFragment;
import com.roly.nfc.crypto.util.EncryptionUtils;
import com.roly.nfc.crypto.util.NfcUtils;
@EActivity(R.layout.activity_note_editer)
@OptionsMenu(R.menu.cryptonfc_addnote_action)
public class EditNoteActivity extends FragmentActivity{
@ViewById
EditText title;
@ViewById
EditText content;
private KeyPickerDialogFragment dialogFragment;
private NfcAdapter adapter;
private IntentFilter[] intentFiltersArray;
private PendingIntent pi;
private String[][] techList;
private String contentValue;
private String titleValue;
private long id;
@OptionsItem(R.id.save_note)
public void saveNote(){
if(title.getText().length()<1)
Toast.makeText(this, "Invalid title", Toast.LENGTH_LONG).show();
else if(content.getText().length()<1)
Toast.makeText(this, "Invalid content", Toast.LENGTH_LONG).show();
else{
contentValue = content.getText().toString();
titleValue = title.getText().toString();
FragmentManager fragmentManager = getSupportFragmentManager();
dialogFragment.show(fragmentManager, "KeyPicker");
registerNFC();
}
}
@AfterViews
public void init(){
Intent intent = getIntent();
id = intent.getLongExtra("id", -1);
if (id > -1) {
titleValue = intent.getStringExtra("title");
contentValue = intent.getStringExtra("content");
title.setText(titleValue);
content.setText(contentValue);
}
dialogFragment = new KeyPickerDialogFragment();
setForegroundListener();
adapter = NfcAdapter.getDefaultAdapter(this);
}
public void registerNFC(){
adapter.enableForegroundDispatch(this, pi, intentFiltersArray, techList);
}
public void unregisterNFCIfNeeded(){
adapter.disableForegroundDispatch(this);
}
protected void setForegroundListener() {
adapter = NfcAdapter.getDefaultAdapter(this);
pi = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter old_ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
old_ndef.addDataScheme("vnd.android.nfc");
old_ndef.addDataAuthority("ext", null);
old_ndef.addDataPath("/CryptoNFCKey", PatternMatcher.PATTERN_PREFIX);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndef.addDataScheme("vnd.android.nfc");
ndef.addDataAuthority("ext", null);
ndef.addDataPath("/r0ly.fr:CryptoNFCKey",PatternMatcher.PATTERN_PREFIX);
intentFiltersArray = new IntentFilter[] {old_ndef, ndef};
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED)){
Parcelable[] messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if(messages.length == 0){
error("The tag you are using doesn't contains any inforations");
return;
}
extractKey(messages);
}
}
@Background
public void extractKey(Parcelable[] messages){
NdefMessage ndef = (NdefMessage) messages[0];
NdefRecord[] records= NfcUtils.getNdefRecords(ndef);
byte[] payload=records[0].getPayload();
int keyLength = payload[0] & 0077;
byte[] keyData = new byte[keyLength];
try{
System.arraycopy(payload, 1, keyData, 0, keyLength);
}catch (ArrayIndexOutOfBoundsException e) {
error("An error occured while reading key on your tag");
return;
}
SecretKey key = new SecretKeySpec(keyData, "DES");
String encrypted;
try {
encrypted = EncryptionUtils.encrypt(key, contentValue);
} catch (GeneralSecurityException | UnsupportedEncodingException e) {
error("An error occured while encrypting text content");
return;
}
ContentValues values = new ContentValues(2);
values.put(NoteDatabase.KEY_TITLE, titleValue);
values.put(NoteDatabase.KEY_BODY, encrypted);
Uri uri = NoteProvider.CONTENT_URI;
Uri insertUri = null;
int update = 0;
if (id > -1) {
uri = ContentUris.withAppendedId(uri, id);
update = getContentResolver().update(uri, values, null, null);
} else {
insertUri = getContentResolver().insert(uri, values);
id = ContentUris.parseId(insertUri);
}
if(insertUri != null || update > 0){
success(encrypted);
} else {
error("An error occured while saving note");
}
}
@Override
protected void onResume() {
super.onResume();
if (dialogFragment.isVisible()) {
registerNFC();
} else {
unregisterNFCIfNeeded();
}
}
@Override
protected void onPause() {
super.onPause();
if (adapter.isEnabled()) {
unregisterNFCIfNeeded();
}
}
@UiThread
public void success(String encrypted) {
Toast.makeText(this, "The note has been encrypted and saved.", Toast.LENGTH_LONG).show();
dialogFragment.dismiss();
content.setText(encrypted);
}
@UiThread
public void error(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
dialogFragment.dismiss();
}
}