diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6f4c369..ed1e174 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -21,6 +21,10 @@
+
+
0) && (Integer.parseInt(txt_server_port.getText().toString()) < 65535)) { // check for valid port
txt_server_port.setText(String.valueOf(Integer.parseInt(txt_server_port.getText().toString())));
- } else txt_server_port.setText(String.valueOf(62201));
+ } else {
+ txt_server_port.setText(String.valueOf(62201));
+ }
} catch (NumberFormatException ex) {
txt_server_port.setText(String.valueOf(62201));
}
if (txt_NickName.getText().toString().equalsIgnoreCase("")) { // Need to create a new Nick
toast.setText("You Must choose a unique Nickname."); // choosing a used nick will just overwrite it. So really
toast.show();
+ } else if (!(txt_ports.getText().toString().matches("tcp/\\d.*") || txt_ports.getText().toString().matches("udp/\\d.*"))) {
+ toast.setText("Access ports must be in the form of 'tcp/22'");
+ toast.show();
} else if (spn_allowip.getSelectedItem().toString().equalsIgnoreCase("Allow IP") && (!ipValidate.isValid(txt_allowIP.getText().toString()))){ //Have to have a valid ip to allow, if using allow ip
toast.setText("You Must supply a valid IP address to 'Allow IP'.");
toast.show();
@@ -219,7 +227,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
} else if (spn_ssh.getSelectedItem().toString().equalsIgnoreCase("Juicessh")) {
config.SSH_CMD = "juice:" + juice_adapt.getConnectionName(spn_juice.getSelectedItemPosition());
config.juice_uuid = juice_adapt.getConnectionId(spn_juice.getSelectedItemPosition());
- Log.v("fwknop2", "Connection Name is: " + juice_adapt.getConnectionName(spn_juice.getSelectedItemPosition()));
} else {
config.juice_uuid = UUID.fromString("00000000-0000-0000-0000-000000000000");
config.SSH_CMD = "";
@@ -235,8 +242,14 @@ public boolean onOptionsItemSelected(MenuItem item) {
if(activity instanceof ConfigListActivity) {
ConfigListActivity myactivity = (ConfigListActivity) activity;
myactivity.onItemSaved();
+
+ } else {
+ ConfigDetailActivity myactivity = (ConfigDetailActivity) activity;
+ myactivity.onBackPressed();
}
}
+ } else {
+ return false;
}
return super.onOptionsItemSelected(item);
}
@@ -244,11 +257,8 @@ public boolean onOptionsItemSelected(MenuItem item) {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { // This handles the qrcode results
- Log.v("fwknop2", "Detail fragment activity result");
if (requestCode == 0) {
-
if (resultCode == Activity.RESULT_OK) {
-
String contents = data.getStringExtra("SCAN_RESULT");
for (String stanzas: contents.split(" ")){
String[] tmp = stanzas.split(":");
@@ -287,8 +297,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
View rootView = inflater.inflate(R.layout.fragment_config_detail, container, false);
active_Nick = getArguments().getString("item_id");
myJuice = new PluginContract();
- // do something here to get the list of nicks
-
//Handlers for the input fields
txt_NickName = (TextView) rootView.findViewById(R.id.NickName);
@@ -317,8 +325,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
juice_adapt = new ConnectionSpinnerAdapter(getActivity());
spn_juice.setAdapter(juice_adapt);
-
- //connectionListLoader.setOnLoadedListener(connectionListLoader.OnLoadedListener());
spn_allowip = (Spinner) rootView.findViewById(R.id.allowip);
ArrayAdapter adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.spinner_options, android.R.layout.simple_spinner_item);
@@ -348,7 +354,6 @@ public void onItemSelected(AdapterView> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
-
if (parent.getItemAtPosition(pos).toString().equalsIgnoreCase("None")) {
lay_sshcmd.setVisibility(View.GONE);
spn_juice.setVisibility(View.GONE);
@@ -433,7 +438,7 @@ public void onNothingSelected(AdapterView> parent) {}
});
//Below is the loading of a saved config
- if (active_Nick.equalsIgnoreCase("New Config")) {
+ if (active_Nick.equalsIgnoreCase("")) {
txt_NickName.setText("");
config.SSH_CMD = "";
txt_HMAC.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
diff --git a/app/src/main/java/biz/incomsystems/fwknop2/ConfigListActivity.java b/app/src/main/java/biz/incomsystems/fwknop2/ConfigListActivity.java
index a628311..2ae6d16 100644
--- a/app/src/main/java/biz/incomsystems/fwknop2/ConfigListActivity.java
+++ b/app/src/main/java/biz/incomsystems/fwknop2/ConfigListActivity.java
@@ -16,12 +16,13 @@
*/
package biz.incomsystems.fwknop2;
+import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
-import android.util.Log;
import java.util.List;
@@ -44,7 +45,7 @@
public class ConfigListActivity extends FragmentActivity
implements ConfigListFragment.Callbacks {
ConfigDetailFragment fragment;
- private boolean mTwoPane; // Whether in two-pane mode.
+ public boolean mTwoPane; // Whether in two-pane mode.
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -64,12 +65,18 @@ protected void onCreate(Bundle savedInstanceState) {
.findFragmentById(R.id.config_list))
.setActivateOnItemClick(true);
}
+ SharedPreferences prefs = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
+ boolean haveWeShownPreferences = prefs.getBoolean("HaveShownPrefs", false);
+
+ if (!haveWeShownPreferences) {
+ Intent detailIntent = new Intent(this, HelpActivity.class);
+ startActivity(detailIntent);
+ }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- Log.v("fwknop2", "onActivityResult in activity");
for (Fragment fragment : getSupportFragmentManager().getFragments())
// this overcomes what may be a bug in the android framework. Pushes the result into fragment so it can get to the nested class.
{
diff --git a/app/src/main/java/biz/incomsystems/fwknop2/ConfigListFragment.java b/app/src/main/java/biz/incomsystems/fwknop2/ConfigListFragment.java
index 2cebc2f..0621365 100644
--- a/app/src/main/java/biz/incomsystems/fwknop2/ConfigListFragment.java
+++ b/app/src/main/java/biz/incomsystems/fwknop2/ConfigListFragment.java
@@ -17,11 +17,13 @@
package biz.incomsystems.fwknop2;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
-import android.util.Log;
import android.view.ContextMenu;
+import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
@@ -45,6 +47,7 @@
*/
public class ConfigListFragment extends ListFragment {
public ArrayAdapter customAdapter;
+ private AdapterView.AdapterContextMenuInfo info;
ArrayList array_list = new ArrayList();
DBHelper mydb;
SendSPA OurSender;
@@ -100,6 +103,7 @@ public ConfigListFragment() {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
mydb = new DBHelper(getActivity());
array_list = mydb.getAllConfigs();
OurSender = new SendSPA();
@@ -111,6 +115,12 @@ public void onCreate(Bundle savedInstanceState) {
setListAdapter(customAdapter);
}
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.list_menu, menu);
+ }
+
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -120,8 +130,31 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
}
+
}
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == R.id.detail_help) {
+ Intent detailIntent = new Intent(getActivity(), HelpActivity.class);
+ startActivity(detailIntent);
+ } else if (id == R.id.new_item) {
+ Activity activity = getActivity();
+ ConfigListActivity myactivity = (ConfigListActivity) activity;
+ if (myactivity.mTwoPane){
+ mCallbacks.onItemSelected("");
+ getListView().setItemChecked(mActivatedPosition, false);
+ } else {
+ Intent detailIntent = new Intent(getActivity(), ConfigDetailActivity.class);
+ detailIntent.putExtra(ConfigDetailFragment.ARG_ITEM_ID, "");
+ startActivity(detailIntent);
+ }
+
+ } else {
+ return false;
+ }
+ return true;
+ }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@@ -140,23 +173,23 @@ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMen
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = this.getActivity().getMenuInflater();
- inflater.inflate(R.menu.listmenu, menu);
+ inflater.inflate(R.menu.list_longtap_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
customAdapter = (ArrayAdapter) getListAdapter();
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
- String nick = ((TextView) info.targetView).getText().toString();
+ info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.delete: // Deleting the selected option
- mydb.deleteConfig(nick);
- array_list.remove(info.position);
- customAdapter.notifyDataSetChanged();
- mydb.close();
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage("Are you sure?").setPositiveButton("Yes", dialogClickListener)
+ .setNegativeButton("No", dialogClickListener).show();
+
return true;
case R.id.knock:
+ String nick = ((TextView) info.targetView).getText().toString();
OurSender.send(nick, getActivity());
default:
@@ -170,8 +203,27 @@ public void onUpdate() {
array_list.addAll(mydb.getAllConfigs());
customAdapter.notifyDataSetChanged();
mydb.close();
- Log.v("fwknop2", "onUpdate runs");
}
+ DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which){
+ case DialogInterface.BUTTON_POSITIVE:
+ //Yes button clicked
+
+ String nick = ((TextView) info.targetView).getText().toString();
+ mydb.deleteConfig(nick);
+ array_list.remove(info.position);
+ customAdapter.notifyDataSetChanged();
+
+ break;
+
+ case DialogInterface.BUTTON_NEGATIVE:
+ //No button clicked
+ break;
+ }
+ }
+ };
@Override
public void onAttach(Activity activity) {
@@ -198,9 +250,6 @@ public void onDetach() {
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
-
- // Notify the active callbacks interface (the activity, if the
- // fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(this.getListAdapter().getItem(position).toString());
}
diff --git a/app/src/main/java/biz/incomsystems/fwknop2/ConnectionListLoader.java b/app/src/main/java/biz/incomsystems/fwknop2/ConnectionListLoader.java
index 78cef26..bc69d0d 100644
--- a/app/src/main/java/biz/incomsystems/fwknop2/ConnectionListLoader.java
+++ b/app/src/main/java/biz/incomsystems/fwknop2/ConnectionListLoader.java
@@ -8,7 +8,6 @@
import android.support.v4.content.Loader;
import com.sonelli.juicessh.pluginlibrary.PluginContract;
-import biz.incomsystems.fwknop2.ConnectionSpinnerAdapter;
public class ConnectionListLoader implements LoaderManager.LoaderCallbacks {
diff --git a/app/src/main/java/biz/incomsystems/fwknop2/DBHelper.java b/app/src/main/java/biz/incomsystems/fwknop2/DBHelper.java
index 2e70d14..a114082 100644
--- a/app/src/main/java/biz/incomsystems/fwknop2/DBHelper.java
+++ b/app/src/main/java/biz/incomsystems/fwknop2/DBHelper.java
@@ -151,7 +151,7 @@ public ArrayList getAllConfigs() // This returns an array of Nick Name
}
res.close();
db.close();
- array_list.add("New Config");
+ //array_list.add("New Config");
return array_list;
}
diff --git a/app/src/main/java/biz/incomsystems/fwknop2/HelpActivity.java b/app/src/main/java/biz/incomsystems/fwknop2/HelpActivity.java
new file mode 100644
index 0000000..cac22c9
--- /dev/null
+++ b/app/src/main/java/biz/incomsystems/fwknop2/HelpActivity.java
@@ -0,0 +1,25 @@
+package biz.incomsystems.fwknop2;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.text.Html;
+import android.text.method.LinkMovementMethod;
+import android.widget.TextView;
+
+public class HelpActivity extends FragmentActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_help);
+ TextView textView = (TextView) findViewById (R.id.help_page);
+ textView.setMovementMethod(LinkMovementMethod.getInstance());
+ textView.setTextColor(getResources().getColor(android.R.color.black));
+ textView.setText(Html.fromHtml(getString(R.string.help_page)));
+ SharedPreferences prefs = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
+ SharedPreferences.Editor ed = prefs.edit();
+ ed.putBoolean("HaveShownPrefs", true);
+ ed.apply();
+ }
+}
diff --git a/app/src/main/java/biz/incomsystems/fwknop2/SendSPA.java b/app/src/main/java/biz/incomsystems/fwknop2/SendSPA.java
index f00cedb..bf642c1 100644
--- a/app/src/main/java/biz/incomsystems/fwknop2/SendSPA.java
+++ b/app/src/main/java/biz/incomsystems/fwknop2/SendSPA.java
@@ -40,7 +40,6 @@
public class SendSPA implements OnSessionStartedListener, OnSessionFinishedListener {
DBHelper mydb;
public static Config config;
- Activity ourAct;
ProgressDialog pdLoading;
Boolean ready;
public PluginClient client;
@@ -66,7 +65,6 @@ public class SendSPA implements OnSessionStartedListener, OnSessionFinishedListe
// @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- Log.v("fwknop2", "onActivityResult");
if(requestCode == 2585){
client.gotActivityResult(requestCode, resultCode, data);
}
@@ -75,11 +73,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
@Override
public void onSessionStarted(int i, String s) {
SendSPA.this.isConnected = true;
- Log.v("fwknop2", "Trying to attach");
try {
client.attach(i,s);
} catch (ServiceNotConnectedException ex){
- Log.v("fwknop2", "Error attaching");
+ Log.e("fwknop2", "Error attaching");
}
}
@@ -124,11 +121,7 @@ public int send(String nick, final Activity ourAct) {
} else {
hmac_b64 = "false";
}
- Log.v("fwknop2", config.juice_uuid.toString());
-
final getExternalIP task = new getExternalIP(ourAct);
-
-
task.execute();
return 0;
}
@@ -208,11 +201,10 @@ protected void onPostExecute(String result) {
@Override
public void onClientStarted() {
SendSPA.this.isConnected = true;
- Log.v("fwknop2", SendSPA.config.juice_uuid.toString());
try {
client.connect(mActivity, config.juice_uuid, SendSPA.this, 2585);
} catch (ServiceNotConnectedException ex) {
- Log.v("fwknop2", "not connected error");
+ Log.e("fwknop2", "not connected error");
}
}
@Override
@@ -223,15 +215,12 @@ public void onClientStopped() {
}
pdLoading.dismiss();
- if (!config.SSH_CMD.equalsIgnoreCase("") && !(config.SSH_CMD.contains("juice:")) ) {
- String ssh_uri = "ssh://" + config.SSH_CMD +"@" + config.SERVER_IP + ":" + config.SERVER_PORT + "/#" + config.NICK_NAME;
+ if (!config.SSH_CMD.equalsIgnoreCase("") && !(config.SSH_CMD.contains("juice:")) ) {
+
+ String ssh_uri = "ssh://" + config.SSH_CMD + "/#" + config.NICK_NAME;
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(ssh_uri));
- Log.v("fwknop2", ssh_uri);
- ourAct.startActivity(i);
+ mActivity.startActivity(i);
}
-
}
-
}
-
}
\ No newline at end of file
diff --git a/app/src/main/jni/fwknop_client.c b/app/src/main/jni/fwknop_client.c
index 8441ded..933805f 100644
--- a/app/src/main/jni/fwknop_client.c
+++ b/app/src/main/jni/fwknop_client.c
@@ -66,7 +66,7 @@ jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
fid = (*env)->GetFieldID(env, c, "allowip_str", "Ljava/lang/String;");
jstring jallowip = (*env)->GetObjectField(env, thiz, fid);
const char *allowip_str = (*env)->GetStringUTFChars(env, jallowip, 0);
- LOGV("%s", allowip_str);
+
fid = (*env)->GetFieldID(env, c, "destip_str", "Ljava/lang/String;");
jstring jdestip = (*env)->GetObjectField(env, thiz, fid);
const char *destip_str = (*env)->GetStringUTFChars(env, jdestip, 0);
@@ -96,12 +96,12 @@ jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
const char *fw_timeout_str = (*env)->GetStringUTFChars(env, jfwtimeout, 0);
fid = (*env)->GetFieldID(env, c, "nat_access_str", "Ljava/lang/String;");
- jstring jnat_access_str = (*env)->GetObjectField(env, thiz, fid);
- const char *nat_access_str = (*env)->GetStringUTFChars(env, jnat_access_str, 0);
+ jstring jnat_access_str = (*env)->GetObjectField(env, thiz, fid);
+ const char *nat_access_str = (*env)->GetStringUTFChars(env, jnat_access_str, 0);
- fid = (*env)->GetFieldID(env, c, "server_cmd_str", "Ljava/lang/String;");
- jstring jserver_cmd = (*env)->GetObjectField(env, thiz, fid);
- const char *server_cmd_str = (*env)->GetStringUTFChars(env, jserver_cmd, 0);
+ fid = (*env)->GetFieldID(env, c, "server_cmd_str", "Ljava/lang/String;");
+ jstring jserver_cmd = (*env)->GetObjectField(env, thiz, fid);
+ const char *server_cmd_str = (*env)->GetStringUTFChars(env, jserver_cmd, 0);
/* Sanity checks
*/
@@ -148,12 +148,10 @@ jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
}
else
{
- LOGV("now to memcpy");
memcpy(hmac_str, hmac_key_tmp, hmac_str_len);
}
}
- LOGV("%s", passwd_b64);
if(strcmp(passwd_b64, "true") == 0) {
LOGV("Detected key b64");
key_len = fko_base64_decode(passwd_str,
@@ -169,7 +167,6 @@ jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
memcpy(passwd_str, key_tmp, key_len);
}
}
- LOGV("%i", hmac_str_len);
/* Using an HMAC is optional (currently)
*/
@@ -194,7 +191,6 @@ jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
message_type = FKO_COMMAND_MSG;
fko_set_spa_message_type(ctx, message_type);
res = fko_set_spa_message(ctx, server_cmd_str);
- LOGV("server command: %s", server_cmd_str);
if (res != FKO_SUCCESS) {
strcpy(res_msg, fko_errmsg("Error setting SPA request message", res));
goto cleanup;
@@ -234,7 +230,6 @@ jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
*/
if (nat_access_str[0] != 0x0){
// if nat_access_str is not blank, push it into fko context
- LOGV("Nat Access string is: %s", nat_access_str);
res = fko_set_spa_nat_access(ctx, nat_access_str);
if (res != FKO_SUCCESS) {
strcpy(res_msg, fko_errmsg("Error setting NAT string", res));
diff --git a/app/src/main/res/layout/activity_help.xml b/app/src/main/res/layout/activity_help.xml
new file mode 100644
index 0000000..ac43cc0
--- /dev/null
+++ b/app/src/main/res/layout/activity_help.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_config_detail.xml b/app/src/main/res/layout/fragment_config_detail.xml
index 5463bf1..fe1a1b7 100644
--- a/app/src/main/res/layout/fragment_config_detail.xml
+++ b/app/src/main/res/layout/fragment_config_detail.xml
@@ -333,7 +333,7 @@
android:layout_height="wrap_content"
android:text=""
android:singleLine="true"
- android:textSize="30sp"
+ android:textSize="20sp"
/>
diff --git a/app/src/main/res/layout/spinner_list_item.xml b/app/src/main/res/layout/spinner_list_item.xml
index f74be48..11b1b8c 100644
--- a/app/src/main/res/layout/spinner_list_item.xml
+++ b/app/src/main/res/layout/spinner_list_item.xml
@@ -25,11 +25,12 @@
diff --git a/app/src/main/res/menu/mainmenu.xml b/app/src/main/res/menu/detail_menu.xml
similarity index 99%
rename from app/src/main/res/menu/mainmenu.xml
rename to app/src/main/res/menu/detail_menu.xml
index 9642a32..285845b 100644
--- a/app/src/main/res/menu/mainmenu.xml
+++ b/app/src/main/res/menu/detail_menu.xml
@@ -9,4 +9,6 @@
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/listmenu.xml b/app/src/main/res/menu/list_longtap_menu.xml
similarity index 99%
rename from app/src/main/res/menu/listmenu.xml
rename to app/src/main/res/menu/list_longtap_menu.xml
index c755185..07a8dd7 100644
--- a/app/src/main/res/menu/listmenu.xml
+++ b/app/src/main/res/menu/list_longtap_menu.xml
@@ -3,7 +3,6 @@
-
-
-
diff --git a/app/src/main/res/menu/list_menu.xml b/app/src/main/res/menu/list_menu.xml
new file mode 100644
index 0000000..50bf3ee
--- /dev/null
+++ b/app/src/main/res/menu/list_menu.xml
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a71e0a9..dc1ead6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,6 +2,7 @@
Fwknop2
Config Detail
Capture qr
+ Help
Save config
Delete config
Send knock
@@ -20,4 +21,35 @@
- SSH Uri
- Juicessh
+
+
+ Welcome to fwknop2! This app is for the sending of SPA Packets to a Linux host or router, mainly
+ for opening ports in an iptables firewall. More info
+ at the Cipherdyne web site.
+
+
+ Get started by selecting "New Config" from the menu, and then filling in at least "Nickname", "Server Address",
+ and "Rijndael Key." If you are using luci-app-fwknop on an Openwrt router, you can select the "Capture qr" option from the menu,
+ and use a qr code generated on the router to auto fill the key and hmac data.
+
+If Juicessh is installed, you can autostart a saved Juicessh connection by sellecting Juicessh from the
+ "Run SSH App" menu, and after a brief delay, choosing the desired connection. If you want to use a different
+ SSH app, select "SSH Uri", and then type in your desired Username to connect as. This will use the system\'s
+ default ssh client to try to connect to the port you are opening.
+
+
+ Once the data is filled in, select "Save Config" from the menu. Then, to send a SPA knock, long tap the
+ Saved config you want to use, and select "Send Knock"
+
+
+ Credits: Based on fwknop and libfko written by Michael Rash
+ This app was written by Jonathan Bennett
+ This app is open source software. The source can be found on github. Please report any bugs here.
+ The fwknop2 icon is derived from on a photo by Peter O\'Connor
+
+ Tap the back button to get started.
+
+ ]]>
+