//
// iip-ui.c
//
//
//
//
//-UserX 2002/03/21

#include <stdlib.h>
//#include <stdio.h>

#include "misc/compat.h"

#include "ui/ui.h"
#include "iip/iip-ui.h"
#include "iip/iip.h"
#include "net/noderef.h"
#include "net/nodeserv.h"
#include "misc/global.h"
#include "base/str.h"
#include "crypt/random.h"

#include "base/bignum.h"
#include "crypt/dh.h"
#include "net/protocol.h"
#include "pipe/nodetran.h"
#include "net/sockserv.h"
#include "base/cfg.h"

#include "crypt/random.h"
#include "file/file.h"

#include "pipe/cs-iip1.h"

/**
The configuration front end for IIP.
@author UserX
@name iip-ui
*/
//@{

enum ID_ {
	ID_NONE,
	ID_RADIO_CLIENT_HOST_LOCAL,
	ID_RADIO_CLIENT_HOST_ANY,
	ID_RADIO_CLIENT_HOST_OTHER,
	ID_EDIT_CLIENT_HOST_OTHER,
	ID_EDIT_CLIENT_PORT,

	ID_RADIO_RELAY_NONE,
	ID_RADIO_RELAY_PRIVATE,
	ID_RADIO_RELAY_PUBLIC,
	ID_BUTTON_RELAY_SETTINGS,

	ID_CHECK_AUTO_GET_NODEREF,
	ID_CHECK_AUTO_NODETRANSGET,
	ID_BUTTON_GET_NODEREF,


	ID_EDIT_RELAY_PRIVATE_KEY,
	ID_EDIT_RELAY_PUBLIC_KEY,
	ID_EDIT_RELAY_HOST,
	ID_EDIT_RELAY_PORT,
	ID_BUTTON_RELAY_MAKE_KEY,


	ID_BUTTON_OK,
	ID_BUTTON_CANCEL
};

#define ICN ((UIFuncNotifyUIControl2) iipcsNotify)
#define IRN ((UIFuncNotifyUIControl2) iiprsNotify)

UIEntry uics[] = {

	{UITYPE_COLUMN_START_2, 0, NULL, NULL},

		{UITYPE_BOXSTART, 0, N_("client access"), NULL},
			{UITYPE_RADIOSTART, 0, NULL, NULL},
				{UITYPE_RADIO, ID_RADIO_CLIENT_HOST_LOCAL, N_("localhost (127.0.0.1)"), ICN},
				{UITYPE_RADIO, ID_RADIO_CLIENT_HOST_ANY, N_("any (0.0.0.0)"), ICN},
				{UITYPE_RADIO, ID_RADIO_CLIENT_HOST_OTHER, N_("other"), ICN},
			{UITYPE_RADIOSTOP, 0, NULL, NULL},
			{UITYPE_EDIT, ID_EDIT_CLIENT_HOST_OTHER, N_("other interface address"), ICN},
			{UITYPE_EDIT, ID_EDIT_CLIENT_PORT, N_("port"), ICN},
		{UITYPE_BOXSTOP, 0, NULL, NULL},

	{UITYPE_COLUMN_STOP, 0, NULL, NULL},

		{UITYPE_BOXSTART, 0, N_("node/relay type"), NULL},
			{UITYPE_RADIOSTART, 0, NULL, NULL},
				{UITYPE_RADIO, ID_RADIO_RELAY_NONE, N_("user/transient (no relay)"), ICN},
				{UITYPE_RADIO, ID_RADIO_RELAY_PRIVATE, N_("private relay"), ICN},
				{UITYPE_RADIO, ID_RADIO_RELAY_PUBLIC, N_("public relay"), ICN},
			{UITYPE_RADIOSTOP, 0, NULL, NULL},
			{UITYPE_BUTTON, ID_BUTTON_RELAY_SETTINGS, N_("Relay settings"), ICN},
		{UITYPE_BOXSTOP, 0, NULL, NULL},

	{UITYPE_COLUMN_STOP, 0, NULL, NULL},


	{UITYPE_BOXSTART, 0, N_("getting node.ref by IIP (anonymous)"), NULL},
		{UITYPE_CHECK, ID_CHECK_AUTO_NODETRANSGET, 
N_("Automatically get node.ref when connecting with a client."), ICN},
	{UITYPE_BOXSTOP, 0, NULL, NULL},
	{UITYPE_BOXSTART, 0, N_("getting node.ref by HTTP (not anonymous)"), NULL},
		{UITYPE_CHECK, ID_CHECK_AUTO_GET_NODEREF, 
N_("Automatically get node.ref on starting IIP."), ICN},
		{UITYPE_BUTTON, ID_BUTTON_GET_NODEREF, N_("Get node.ref now"), ICN},
	{UITYPE_BOXSTOP, 0, NULL, NULL},

	{UITYPE_COLUMN_START_2, 0, NULL, NULL},
		{UITYPE_BUTTON, ID_BUTTON_OK, N_("Ok"), ICN},
	{UITYPE_COLUMN_STOP, 0, NULL, NULL},
		{UITYPE_BUTTON, ID_BUTTON_CANCEL, N_("Cancel"), ICN},
	{UITYPE_COLUMN_STOP, 0, NULL, NULL},
	BLANKUIENTRY
};

UIEntry uirs[] = {
	{UITYPE_EDIT_LONG, ID_EDIT_RELAY_PRIVATE_KEY, N_("Private Key"), IRN},
	{UITYPE_EDIT_LONG, ID_EDIT_RELAY_PUBLIC_KEY, N_("Public Key"), IRN},
	{UITYPE_BUTTON, ID_BUTTON_RELAY_MAKE_KEY, N_("Make Key"), IRN},
	{UITYPE_COLUMN_START_2, 0, NULL, NULL},
		{UITYPE_EDIT, ID_EDIT_RELAY_HOST, N_("Public host name/address"), IRN},
	{UITYPE_COLUMN_STOP, 0, NULL, NULL},
		{UITYPE_EDIT, ID_EDIT_RELAY_PORT, N_("Port"), IRN},
	{UITYPE_COLUMN_STOP, 0, NULL, NULL},

	{UITYPE_COLUMN_START_2, 0, NULL, NULL},
		{UITYPE_BUTTON, ID_BUTTON_OK, N_("Ok"), IRN},
	{UITYPE_COLUMN_STOP, 0, NULL, NULL},
		{UITYPE_BUTTON, ID_BUTTON_CANCEL, N_("Cancel"), IRN},
	{UITYPE_COLUMN_STOP, 0, NULL, NULL},
	BLANKUIENTRY
};


int iiprelaychanged = 0;


int iipcsNotify(UIWindow *uiw, UIControl *uic, int notice) {
	int i;

	switch(notice) {
	case UINOTIFY_INIT: //ignore inits should have already been done earlier
		return UINOTIFYRETURN_OK;
	case UINOTIFY_CHANGE:
	case UINOTIFY_ACTIVATED:
		break;
	}

	switch(uic->entry.id) {
	case ID_RADIO_CLIENT_HOST_LOCAL:
	case ID_RADIO_CLIENT_HOST_ANY:
		uicDisable(uiw, ID_EDIT_CLIENT_HOST_OTHER);
		return UINOTIFYRETURN_OK;
	case ID_RADIO_CLIENT_HOST_OTHER:
		uicEnable(uiw, ID_EDIT_CLIENT_HOST_OTHER);
		return UINOTIFYRETURN_OK;
	case ID_EDIT_CLIENT_HOST_OTHER:
		return UINOTIFYRETURN_OK;
	case ID_EDIT_CLIENT_PORT:
		for(i = 0; i < stringLength(uic->stringvalue); i++) {
			if(uic->stringvalue[i] < '0' || uic->stringvalue[i] > '9') {
				uiDialog("IIP", "Port number must actually be a number!", UIDIALOG_OK, UIDIALOG_OK);
				return UINOTIFYRETURN_BAD;
			}
		}
		return UINOTIFYRETURN_OK;
	
	case ID_RADIO_RELAY_NONE:
		uicEnable(uiw, ID_CHECK_AUTO_GET_NODEREF);
		uicEnable(uiw, ID_BUTTON_GET_NODEREF);
		uicEnable(uiw, ID_CHECK_AUTO_NODETRANSGET);
		uicDisable(uiw, ID_BUTTON_RELAY_SETTINGS);
		uicSetCheck(uiw, ID_CHECK_AUTO_NODETRANSGET, 1);
		//todo: check for the presence of relay settings
		uiDialog("IIP", "Once these settings are accepted you will lose any relay settings (and private keys) you have!", UIDIALOG_OK, UIDIALOG_OK);
		return UINOTIFYRETURN_OK;
	case ID_RADIO_RELAY_PRIVATE:
		uicEnable(uiw, ID_CHECK_AUTO_GET_NODEREF);
		uicEnable(uiw, ID_BUTTON_GET_NODEREF);
		uicEnable(uiw, ID_CHECK_AUTO_NODETRANSGET);
		uicEnable(uiw, ID_BUTTON_RELAY_SETTINGS);
		uicSetCheck(uiw, ID_CHECK_AUTO_NODETRANSGET, 1);
		return UINOTIFYRETURN_OK;
	case ID_RADIO_RELAY_PUBLIC:
		uicSetCheck(uiw, ID_CHECK_AUTO_GET_NODEREF, 0);
		uicSetCheck(uiw, ID_CHECK_AUTO_NODETRANSGET, 0);
		uicDisable(uiw, ID_CHECK_AUTO_GET_NODEREF);
		uicDisable(uiw, ID_BUTTON_GET_NODEREF);
		uicDisable(uiw, ID_CHECK_AUTO_NODETRANSGET);
		uicEnable(uiw, ID_BUTTON_RELAY_SETTINGS);
		//todo: caution about use autoget
		return UINOTIFYRETURN_OK;
	case ID_BUTTON_RELAY_SETTINGS:
		iiprsScreen();
		return UINOTIFYRETURN_OK;

	case ID_CHECK_AUTO_GET_NODEREF:
		if(uic->value != 0) {
			uiDialog(_("IIP"), _("Retrieving node.ref by HTTP can be an anonymity concern for some users. If you think you are such a user, leave it disabled."), UIDIALOG_OK, UIDIALOG_OK);
		}
		return UINOTIFYRETURN_OK;
	case ID_CHECK_AUTO_NODETRANSGET:
		return UINOTIFYRETURN_OK;
	case ID_BUTTON_GET_NODEREF:
		if(uiDialog(_("IIP"), _("Retrieving node.ref by HTTP can be an anonymity concern for some users. If you think you are such a user, choose 'no'."), UIDIALOG_YES | UIDIALOG_NO, UIDIALOG_NO) == UIDIALOG_YES) {
			if(nodeservGetNodeRefs(refgetpage, refgethost, refgetport)) {
				uiDialog(_("IIP - Node.ref fetch error"), _("A problem was encontered while retreiving node.ref."), UIDIALOG_OK, UIDIALOG_OK);
			} else {
				uiDialog(_("IIP - Node.ref retrieved OK"), _("Successfully retrieved node.ref."), UIDIALOG_OK, UIDIALOG_OK);
			}
		}
		return UINOTIFYRETURN_OK;

	case ID_BUTTON_OK:
		//todo: all the CS option saving
		
		return iipcsOK(uiw);
	case ID_BUTTON_CANCEL:
		return UINOTIFYRETURN_EXIT;
	}
	return UINOTIFYRETURN_OK;
}

void iipcsScreen(void) {
	UIWindow *uiw;

	if(randomentropyneeded != 0) {
		uiGetEntropy(_("IIP - Entropy needed"), N_("IIP has insufficient random data to start with."), 650);
	}

	iiprelaychanged = 0;

	uiw = uiwMake(_("IIP - Settings"));
	uiwAddControls(uiw, uics);
	iipcsInit(uiw);
	uiwRun(uiw);
	uiwFree(uiw);
}

void iipcsInit(UIWindow *uiw) {
	NodeRef *nr = NULL;
	char *s;
	int i;

	nraCheckMake();
//find a client listenref
	for(i = 0; i < LNRA->size; i++) {
		if(stringCaseCompare(LNRA->data[i].Special, "entry") == 0) {
			nr = &LNRA->data[i];
			break;
		}
	}
//add a listenref if none found
	if(nr == NULL) {
		nr = lnraAdd("127.0.0.1");
		nr->Special = "entry";
		if(localPort == -1) {
			//localPort = 6667;
			nr->PortNum = 6667; //localPort;
		}
		nr->Protocol = networkProtocol;
		nr->PublicKey = networkKey;
	}
	if(stringCompare(nr->HostName, "127.0.0.1") == 0) {
		uicSetRadio(uiw, ID_RADIO_CLIENT_HOST_LOCAL);
		uicDisable(uiw, ID_EDIT_CLIENT_HOST_OTHER);
	} else if(stringCompare(nr->HostName, "0.0.0.0") == 0) {
		uicSetRadio(uiw, ID_RADIO_CLIENT_HOST_ANY);
		uicDisable(uiw, ID_EDIT_CLIENT_HOST_OTHER);
	} else {
		uicSetRadio(uiw, ID_RADIO_CLIENT_HOST_OTHER);
		uicEnable(uiw, ID_EDIT_CLIENT_HOST_OTHER);
		uicSetString(uiw, ID_EDIT_CLIENT_HOST_OTHER, nr->HostName);
	}

	s = intToString(nr->PortNum);
	uicSetString(uiw, ID_EDIT_CLIENT_PORT, s);
	stringFree(s);

//find any relay settings
	nr = NULL;
	for(i = 0; i < LNRA->size; i++) {
		if(stringCaseCompare(LNRA->data[i].Special, "entry") != 0) {
			nr = &LNRA->data[i];
			break;
		}
	}
	if(nr == NULL) {
		uicSetRadio(uiw, ID_RADIO_RELAY_NONE);
		uicDisable(uiw, ID_BUTTON_RELAY_SETTINGS);
		uicEnable(uiw, ID_CHECK_AUTO_GET_NODEREF);
		uicEnable(uiw, ID_BUTTON_GET_NODEREF);
		uicEnable(uiw, ID_CHECK_AUTO_NODETRANSGET);
	} else {
		if(publicrelaynode == 0) {
			uicSetRadio(uiw, ID_RADIO_RELAY_PRIVATE);
			uicEnable(uiw, ID_BUTTON_RELAY_SETTINGS);
			uicEnable(uiw, ID_CHECK_AUTO_GET_NODEREF);
			uicEnable(uiw, ID_BUTTON_GET_NODEREF);
			uicEnable(uiw, ID_CHECK_AUTO_NODETRANSGET);
		} else {
			uicSetRadio(uiw, ID_RADIO_RELAY_PUBLIC);
			uicEnable(uiw, ID_BUTTON_RELAY_SETTINGS);
			uicDisable(uiw, ID_CHECK_AUTO_GET_NODEREF);
			uicDisable(uiw, ID_BUTTON_GET_NODEREF);
			uicDisable(uiw, ID_CHECK_AUTO_NODETRANSGET);
		}
	}

	uicSetCheck(uiw, ID_CHECK_AUTO_GET_NODEREF, autogetnoderefs);
	uicSetCheck(uiw, ID_CHECK_AUTO_NODETRANSGET, nodetransget);


	return;

}

int iiprsNotify(UIWindow *uiw, UIControl *uic, int notice) {
	char *s;
	int i;
	BigNum *privkey;
	BigNum *pubkey;

	switch(notice) {
	case UINOTIFY_INIT:
		return UINOTIFYRETURN_OK;
	case UINOTIFY_CHANGE:
	case UINOTIFY_ACTIVATED:
		break;
	}
	switch(uic->entry.id) {
	case ID_EDIT_RELAY_PRIVATE_KEY:
		//todo: format checking
		return UINOTIFYRETURN_OK;
	case ID_EDIT_RELAY_PUBLIC_KEY:
		//todo: format checking
		return UINOTIFYRETURN_OK;
	case ID_EDIT_RELAY_HOST:
		//todo: format checking
		return UINOTIFYRETURN_OK;
	case ID_EDIT_RELAY_PORT:
		for(i = 0; i < stringLength(uic->stringvalue); i++) {
			if(uic->stringvalue[i] < '0' || uic->stringvalue[i] > '9') {
				uiDialog(_("IIP"), _("Port number must actually be a number!"), UIDIALOG_OK, UIDIALOG_OK);
				return UINOTIFYRETURN_BAD;
			}
		}
		return UINOTIFYRETURN_OK;
	case ID_BUTTON_RELAY_MAKE_KEY:
		//todo: prompt before making key
		s = uicGetString(uiw, ID_EDIT_RELAY_PRIVATE_KEY);
		if(!isStringBlank(s)) {
			if(uiDialog(_("IIP"), _("This will make a new key pair. You will lose your existing key pair. Do you wish to continue?"), UIDIALOG_YES | UIDIALOG_NO, UIDIALOG_NO) == UIDIALOG_NO) {
				stringFree(s);
				return UINOTIFYRETURN_OK;
			}
		}
		stringFree(s);

		privkey = dhGeneratePrivKey(CSIIP1_DH_PRIV_LENGTH); //dhGetExponentLength(1024));
		pubkey = dhGeneratePubKey(1024, privkey);
		
		s = bignumToHex(privkey);
		uicSetString(uiw, ID_EDIT_RELAY_PRIVATE_KEY, s);
		stringFree(s);

		s = bignumToHex(pubkey);
		uicSetString(uiw, ID_EDIT_RELAY_PUBLIC_KEY, s);
		stringFree(s);

		bignumFree(privkey);
		bignumFree(pubkey);

		return UINOTIFYRETURN_OK;
	case ID_BUTTON_OK:
		//todo: all the RS option saving
		return iiprsOK(uiw);
	case ID_BUTTON_CANCEL:
		return UINOTIFYRETURN_EXIT;
	}
	return UINOTIFYRETURN_OK;
}

void iiprsScreen(void) {
	UIWindow *uiw;
	uiw = uiwMake(_("IIP - Relay Settings"));
	uiwAddControls(uiw, uirs);
	iiprsInit(uiw);
	uiwRun(uiw);
	uiwFree(uiw);
}

void iiprsInit(UIWindow *uiw) {
	char *s;
	BigNum *privkey;
	BigNum *pubkey;
	int i;
	NodeRef *nr = NULL;

	for(i = 0; i < LNRA->size; i++) {
		if(stringCaseCompare(LNRA->data[i].Special, "entry") != 0) {
			nr = &LNRA->data[i];
			break;
		}
	}
/*
	if(nr == NULL) {
		nr = lnraAdd("0.0.0.0");
		nr->PortNum = 1024 + randomint(30000);//PROTOCOL_DEFAULTPORT;
		nr->Protocol = "crypt:raw";
	}
*/
	if(!isStringBlank(hostname)) {
		uicSetString(uiw, ID_EDIT_RELAY_HOST, hostname);
	}
	if(nr != NULL) {
		if(!isStringBlank(nr->PrivateKey)) {
			uicSetString(uiw, ID_EDIT_RELAY_PRIVATE_KEY, nr->PrivateKey);

			privkey = bignumFromHex(nr->PrivateKey);
			pubkey = dhGeneratePubKey(1024, privkey);
			s = bignumToHex(pubkey);
			bignumFree(privkey);
			bignumFree(pubkey);

			uicSetString(uiw, ID_EDIT_RELAY_PUBLIC_KEY, s);
			stringFree(s);
		}
		s = intToString(nr->PortNum);
		uicSetString(uiw, ID_EDIT_RELAY_PORT, s);
		stringFree(s);
	} else {
		s = intToString(1024 + randomint(30000));
		uicSetString(uiw, ID_EDIT_RELAY_PORT, s);
		stringFree(s);
	}
}


int iipcsOK(UIWindow *uiw) {
	int newport;
	char *host;
	int i;
	NodeRef *nr = NULL;
	int usernode = 0;

	newport = atoi(uicGetString(uiw, ID_EDIT_CLIENT_PORT));
	if(!(newport >=1 && newport <=65535)) {
		uiDialog(_("IIP"), _("Bad port number must be between 1 and 65535"), UIDIALOG_OK, UIDIALOG_OK);
		return UINOTIFYRETURN_BAD;
	}
	switch(uicGetRadio(uiw, ID_RADIO_CLIENT_HOST_LOCAL)) {
	case ID_RADIO_CLIENT_HOST_LOCAL:
		host = "127.0.0.1";
		break;
	case ID_RADIO_CLIENT_HOST_ANY:
		host = "0.0.0.0";
		break;
	case ID_RADIO_CLIENT_HOST_OTHER:
		host = uicGetString(uiw, ID_EDIT_CLIENT_HOST_OTHER);
		if(isStringBlank(host)) {
			uiDialog(_("IIP"), _("No client access host address specified."), UIDIALOG_OK, UIDIALOG_OK);
			stringFree(host);
			return UINOTIFYRETURN_BAD;
		}
		break;
	default:
		uiDialog(_("IIP"), _("No client access host address specified."), UIDIALOG_OK, UIDIALOG_OK);
		return UINOTIFYRETURN_BAD;
	}

	
	
	autogetnoderefs = uicGetValue(uiw, ID_CHECK_AUTO_GET_NODEREF);
	nodetransget = uicGetValue(uiw, ID_CHECK_AUTO_NODETRANSGET);

	switch(uicGetRadio(uiw, ID_RADIO_RELAY_NONE)) {
	case ID_RADIO_RELAY_NONE:
		publicrelaynode = 0;
		usernode = 1;
		retries = 5;
		break;
	case ID_RADIO_RELAY_PRIVATE:
		publicrelaynode = 0;
		retries = 2;
		break;
	case ID_RADIO_RELAY_PUBLIC:
		publicrelaynode = 1;
		retries = 0;
		break;
	default:
		uiDialog(_("IIP"), _("No client access host address specified."), UIDIALOG_OK, UIDIALOG_OK);
		return UINOTIFYRETURN_BAD;
	}


	if(usernode != 0) {
		for(i = 0; i < LNRA->size; /*i++ at end of loop*/) {
			if(stringCaseCompare(LNRA->data[i].Special, "entry") != 0) {
				lnraDelete(i);
				continue;
			}
			i++;
		}
	}
	for(i = 0; i < LNRA->size; i++) {
		if(stringCaseCompare(LNRA->data[i].Special, "entry") == 0) {
			nr = &LNRA->data[i];
			break;
		}
	}
//todo: handle the case of if there is no entry noderef
	if(nr != NULL) {
		stringFree(nr->HostName);
		nr->PortNum = newport;
		nr->HostName = stringCopy(host);
	}
	for(i = 0; i < LNRA->size; i++) {
		if(LNRA->data[i].PortNum == localPort) {
			LNRA->data[i].PortNum = newport;
		}
	}

	localPort = newport;

	stringFree(host);


	sockservStartListen();
	nodeservWriteListenRef();
	configWrite();


	if(publicrelaynode) {
		return iipDoRelaySubmit();
	}


	return UINOTIFYRETURN_EXIT;

}


int iipDoRelaySubmit(void) {
	int i;
	NodeRef *nr = NULL;
	BigNum *privkey;
	BigNum *pubkey;
	char *spubkey;

	i = uiDialog(_("IIP - Submit node?"), _("Do you wish to announce your relay node to the network?"), UIDIALOG_YES | UIDIALOG_NO, UIDIALOG_NO);
	if(i == UIDIALOG_YES) {
		for(i = 0; i < LNRA->size; i++) {
			if(stringCaseCompare(LNRA->data[i].Special, "entry") != 0) {
				nr = &LNRA->data[i];
				break;
			}
		}
		if(nr == NULL) {
			uiDialog(_("IIP - Submit node."), _("Could not find relay setings. Please got to relay settings and configure your node."), UIDIALOG_OK, UIDIALOG_OK);
			return UINOTIFYRETURN_BAD;
		}
		nr = noderefCopy(nr);

		privkey = bignumFromHex(nr->PrivateKey);
		pubkey = dhGeneratePubKey(1024, privkey);
		spubkey = bignumToHex(pubkey);
		
		stringFree(nr->PublicKey);
		stringFree(nr->HostName);
		nr->PublicKey = stringCopy(spubkey);
		nr->HostName = stringCopy(hostname);
		if(nodeservSubmitNode(nr, informpage, informhost, informport) != 0) {
			uiDialog(_("IIP - Submit error"), _("A problem was encontered while submitting your noderef."), UIDIALOG_OK, UIDIALOG_OK);
		} else {
			uiDialog(_("IIP - Noderef submit OK"), _("Your noderef was successfully announced\nfirewall note: allow access to the port specified in relay settings."), UIDIALOG_OK, UIDIALOG_OK);
		}
		noderefFree(nr);

		if(iiprelaychanged != 0) {
			if(nodeservGetNodeRefs(refgetpublicrelaypage, refgethost, refgetport)) {
				uiDialog(_("IIP - Node.ref fetch error"), _("A problem was encontered while retreiving node.ref."), UIDIALOG_OK, UIDIALOG_OK);
			} else {
				uiDialog(_("IIP - Node.ref retrieved OK"), _("Successfully retrieved node.ref."), UIDIALOG_OK, UIDIALOG_OK);
			}
		}
	}
	return UINOTIFYRETURN_EXIT;
}

int iiprsOK(UIWindow *uiw) {
	char *s;
	char *sprivkey;
	char *spubkey;
	NodeRef *nr = NULL;
	FileHandle *fh;
	int newport;
	int i;

//get host
	s = uicGetString(uiw, ID_EDIT_RELAY_HOST);
//get port
	newport = atoi(uicGetString(uiw, ID_EDIT_RELAY_PORT));
	if(!(newport >=1 && newport <=65535)) {
		uiDialog(_("IIP"), _("Bad port number must be between 1 and 65535"), UIDIALOG_OK, UIDIALOG_OK);
		return UINOTIFYRETURN_OK;
	}
//get keys
	sprivkey = uicGetString(uiw, ID_EDIT_RELAY_PRIVATE_KEY);
	//todo: calc pubkey from private key
	spubkey = uicGetString(uiw, ID_EDIT_RELAY_PUBLIC_KEY);

//find the noderef
	for(i = 0; i < LNRA->size; i++) {
		if(stringCaseCompare(LNRA->data[i].Special, "entry") != 0) {
			nr = &LNRA->data[i];
			break;
		}
	}
//create noderef if not found
	if(nr == NULL) {
		nr = lnraAdd("0.0.0.0");
		nr->PortNum = 0;
		nr->Protocol = stringCopy(relayprotocol);//"crypt:raw";
	}
//update the noderef
	if(nr != NULL) {
		if(nr->PortNum != newport) {
			iiprelaychanged = 1;
		}
		if(stringCaseCompare(nr->PrivateKey, sprivkey) != 0) {
			iiprelaychanged = 1;
		}
		nr->PortNum = newport;
		nr->PrivateKey = stringReplace(nr->PrivateKey, sprivkey);
	}
	if(stringCaseCompare(hostname, s) != 0) {
		iiprelaychanged = 1;
	}


//update the stored hostname
	hostname = stringReplace(hostname, s);

//write mynode.ref
	fh = fileOpen("@mynode.ref", "w");
	if(!isStringBlank(networkKey)) {
		//fprintf(fh, "networkid = %s\n", networkKey);
		fileWriteString(fh, stringCopyMany(
				"networkid = ",
				networkKey,
				"\n",
			NULL));
	}
	if(!isStringBlank(networkProtocol)) {
		//fprintf(fh, "networkprotocol = %s\n", networkProtocol);
		fileWriteString(fh, stringCopyMany(
				"networkprotocol = ",
				networkProtocol,
				"\n",
			NULL));
	}
	//fprintf(fh, "host = %s\n", s);
	//fprintf(fh, "port = %d\n", nr->PortNum);
	//fprintf(fh, "protocol = %s\n", nr->Protocol);
	fileWriteString(fh, stringCopyMany(
			"host = ",
			s,
			"\n",
		NULL));
	fileWriteString(fh, stringJoinMany(
			"port = ",
			intToString(nr->PortNum),
			"\n",
		NULL));
	fileWriteString(fh, stringCopyMany(
			"protocol = ",
			nr->Protocol,
			"\n",
		NULL));

	if(!isStringBlank(spubkey)) {
		//fprintf(fh, "publickey = %s\n", spubkey);
		fileWriteString(fh, stringCopyMany(
				"publickey = ",
				spubkey,
				"\n",
			NULL));
	} else {
		stringFree(spubkey);
	}
	fileClose(fh);

//restart the socks listener
	sockservStartListen();
//write the listenrefs
	nodeservWriteListenRef();
//write the config file
	configWrite();

	return UINOTIFYRETURN_EXIT;
}

//@}

