/*************************************************************************\
* "$RCSfile: CNetwork.cpp,v $"                                            *
***************************************************************************
* Information by CVS or VSS:                                              *
*     Last check in on: $Date: 2010-10-04 14:03:19 $                      *
*     by                $Author: schluckebier $
*     Revision        : $Revision: 1.1 $                                 *
\*************************************************************************/
/*! \file CNetwork.cpp
*	\brief Network Class
*	\author (c) 2006 - 2013 IMAGO Technologies GmbH
*	\addtogroup Parameter Parameter in INI files
*	\{
*		\section ParaN Parameters for Network in ETHERNET.INI
*		\p IPAddress: TCP/IP address (0.0.0.0 for DHCP)\n
*		\p IpSubnetMask: Subnet mask (255.255.255.0)\n
*		\p IpDefaultGw: Address of default gateway\n
*		\p IpDNSServer: Address of DNS server\n
*		\p HostName: Host name of VisionBox\n
*		\p DomainName: Domain name\n
*	\}
*	\addtogroup Ethernet Network Functions
*	\{
*	\brief Functions for Network
**************************************************************************/

#include <std.h>
#include <tsk.h>
#include <clk.h>
#include <string.h>
#include "vision_box.h"
#include "Config.h"
#include "GUI_Lib.h"
#ifdef USE_PNG
 #include "PNG_Lib.h"
#endif
#ifdef USE_JPG
 #include "JPEG_Lib.h"
#endif
#include "GBit.h"
#include "CNetwork.hpp"

/*************************************************************************/
CNetwork::CNetwork()
/*************************************************************************/
/*! @brief Constructor
**************************************************************************/
{
	m_NetShowLinks = 1;
	m_NetAutoRedraw = 1;
	m_EthernetIni = NULL;

	if (VIB_GetSerialNumber(m_SerialNumber) < 0)
		sprintf(m_SerialNumber, "SerialnumberInvalid");
}

/*************************************************************************/
void CNetwork::TaskDisplay(VIB_DISPLAYDEVICE *pTcpDisplay, CIMAGE *pDisplayPic)
/*************************************************************************/
/*! @brief Display task for Ethernet display.

	This code looks for a new connected client and updates the screen.
	@param pTcpDisplay Pointer to Ethernet display
	@param pDisplayPic Pointer to \p CIMAGE
**************************************************************************/
{
	int DisplayStatus, OldDisplayStatus = 0;

	fdOpenSession(TSK_self());

	while (1)
	{
		DisplayStatus = GBIT_DisplayStatus(pTcpDisplay);
		if (DisplayStatus == 2 || DisplayStatus && !OldDisplayStatus)
			GUI_Display(pDisplayPic, 0, 0);
		OldDisplayStatus = DisplayStatus;
		VIB_WaitBios(100);
	}
}

/*************************************************************************/
void CNetwork::TaskUDPBroadcast(CNetwork *pThis)
/*************************************************************************/
/*! @brief Receives broadcast UDP requests and sends IP and serial number.
	@param pThis Pointer to CNetwork instance
**************************************************************************/
{
	struct sockaddr_in sa;
	struct sockaddr_in SenderAddr;
	int Broadcast = 1;
	int SenderAddrSize = sizeof(sa);
	int result;
	SOCKET socksend;
	bool bActive = true;
	char Packet[64];

	fdOpenSession(TSK_self());
	srand(CLK_gethtime());

	socksend = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (socksend == INVALID_SOCKET)
	{
		printf("failed socket create (%d)\n", socketerror());
		return;
	}

	setsockopt(socksend, SOL_SOCKET, SO_BROADCAST, (char *)&Broadcast, (int)sizeof(int));

	memset(&sa, 0, sizeof(sa));
	sa.sin_len         = sizeof(sa);
	sa.sin_addr.s_addr = INADDR_ANY;
	sa.sin_port        = htons(UDP_PORT_IN);
	sa.sin_family      = AF_INET;
	if (bind(socksend, &sa, (int)sizeof(sa)) < 0)
	{
		printf("failed bind (%d)\n", socketerror());
		return;
	}

	//=== Check for broadcast message ===
	while (bActive)
	{
		result = recvfrom(socksend, Packet, 64, 0, &SenderAddr, &SenderAddrSize);
		if (result < 0)
		{
			printf("recvfrom failed\n");
		}
		else
		{
			//=== Send IP & Serial ===
			if (strncmp(Packet, "Who?", 4) == 0)
			{
				strcpy(Packet, pThis->m_SerialNumber);

				// send packet
				memset(&sa, 0, sizeof(sa));
				sa.sin_len         = sizeof(sa);
				sa.sin_addr.s_addr = inet_addr("255.255.255.255");
				sa.sin_port        = htons(UDP_PORT_OUT);
				sa.sin_family      = AF_INET;
				VIB_WaitBios(50 + (rand() % 16) * 10);

				if (sendto(socksend, Packet, 64, 0, &sa, (int)sizeof(sa)) < 0)
					printf("sendto failed (%d)\n", socketerror());
			}
			//=== Send features ===
			else if (strncmp(Packet, "Get?", 4) == 0)
			{
				Packet[0] = '#';
				Packet[1] = 1 | 2 | 4 | 8 | 0x10; // Reset | change IP | TCP Display | change subnet mask | Web Server
				Packet[2] = '\0';
				Packet[3] = '\0';

				// Get subnet mask
				*(unsigned int *)(Packet + 4) = inet_addr(pThis->m_EthernetIni->getValue("IpSubnetMask", "255.255.255.0"));

				// MAC Address
				if (GBIT_GetPhyInfo((unsigned char*)Packet + 10, NULL) == 0)
					Packet[1] |= 0x40;

				// App name
				Packet[1] |= 0x80;
				strcpy(Packet + 16, "Example");

				// Send packet
				memset(&sa, 0, sizeof(sa));
				sa.sin_len         = sizeof(sa);
				sa.sin_addr.s_addr = inet_addr("255.255.255.255");
				sa.sin_port        = htons(UDP_PORT_OUT);
				sa.sin_family      = AF_INET;
				VIB_WaitBios(50 + (rand() % 16) * 10);

				if (sendto(socksend, Packet, 48, 0, &sa, (int)sizeof(sa)) < 0)
					printf("sendto failed (%d)\n", socketerror());
			}
			//=== Reset ===
			else if (strncmp(Packet, "Res!", 4) == 0)
			{
				if (strncmp(&Packet[4], pThis->m_SerialNumber, 32) == 0)
				{
					if (!strncmp(getenv("OS"), "Windows", 7)) // Check for JTAG connection
						exit(0);
					VIB_Reboot();
				}
			}
			//=== Change IP-Address ===
			else if (strncmp(Packet, "CIP!", 4) == 0)
			{
				if (strncmp(&Packet[4], pThis->m_SerialNumber, 32) == 0)
				{
					char IpStr[20], SubnetStr[20];
					unsigned char Ip0 = (unsigned char) Packet[36];
					unsigned char Ip1 = (unsigned char) Packet[37];
					unsigned char Ip2 = (unsigned char) Packet[38];
					unsigned char Ip3 = (unsigned char) Packet[39];
					sprintf(IpStr, "%d.%d.%d.%d", Ip0, Ip1, Ip2, Ip3);

					if (pThis->m_EthernetIni == NULL)
					{
						printf("Error changing IP-Address to '%s'\n", IpStr);
					}
					else
					{
						pThis->m_EthernetIni->setValue("IPAddress", IpStr);

						if (result < 64 && result >= 44)
						{
							Ip0 = (unsigned char) Packet[40];
							Ip1 = (unsigned char) Packet[41];
							Ip2 = (unsigned char) Packet[42];
							Ip3 = (unsigned char) Packet[43];
							sprintf(SubnetStr, "%d.%d.%d.%d", Ip0, Ip1, Ip2, Ip3);
							pThis->m_EthernetIni->setValue("IpSubnetMask", SubnetStr);
						}

						if (pThis->m_EthernetIni->saveToIni(VIB_Drive[1], "ethernet.ini") < 0)
							printf("Error changing IP address to '%s'\n", IpStr);
						else
							printf("IP address changed to '%s'\n", IpStr);
					}
				}
			}
		}
	}
}

/*************************************************************************/
void CNetwork::InitDisplay(CIMAGE *pImage, int *pDviDisplay, int *pGBitDisplay,
	int DefaultWidth, int DefaultHeight)
/*************************************************************************/
/*! @brief Initialization of display.
	@param pImage Pointer to \p CIMAGE
	@param[out] pDviDisplay DVI display active
	@param[out] pGBitDisplay GBit display active
	@param DefaultWidth Default width of TCP display
	@param DefaultHeight Default height of TCP display
**************************************************************************/
{
	static bool bCalled = false;
	bool bDviDisplay;
	bool bGBitDisplay = false;

	if (bCalled)
		return;

#ifndef DM643x
	// *** Initialize DVI/VGA Display ***
	if (VIB_InitDisplay(&m_DisplayA, &m_DisplayB) >= 0)
	{
		bDviDisplay = true;
	}
	else // No DVI/VGA board
#endif
	{
		m_DisplayA.width = DefaultWidth;
		m_DisplayA.height = DefaultHeight;
		bDviDisplay = false;
	}

	*pImage = GUI_CImage(NULL, NULL, NULL, m_DisplayA.width, m_DisplayA.height); // Background image

	if (bDviDisplay)
	{
		GUI_Display(pImage, 0, 0);
		GUI_Display(pImage, 0, 0);
		GUI_MessageBox(NULL, "\nInitializing Ethernet Module...\n\n", NULL, 0);
	}

	if (VIB_HWInfo.CPUID == 0)
	{
		// *** Init Ethernet ***
		if (Init(pImage) >= 0)
			bGBitDisplay = true;
	}

	if (!bGBitDisplay && !bDviDisplay)
	{
		printf("Error: No display found.\n");
		exit(-1);
	}

	// *** Add Ethernet display ***
	m_GuiDisplay = GUI_NewDisplay();
	if (bGBitDisplay)
		GUI_DisplayAddDevice(&m_GuiDisplay, &m_TcpDisplay, 0, 0);
	if (bDviDisplay)
		GUI_DisplayAddDevice(&m_GuiDisplay, &m_DisplayA, 0, 0);
	GUI_SetActiveDisplay(&m_GuiDisplay);

	if (pDviDisplay)
		*pDviDisplay = bDviDisplay;
	if (pGBitDisplay)
		*pGBitDisplay = bGBitDisplay;
	bCalled = true;
}

/*************************************************************************/
int CNetwork::Init(CIMAGE *pDisplayPic)
/*************************************************************************/
/*! @brief Initialization of Ethernet display and FTP server.
	@param pDisplayPic Pointer to \p CIMAGE
	@return Error code
**************************************************************************/
{
	static bool bCalled = false;
	const int Width = m_DisplayA.width;
	const int Height = m_DisplayA.height;
	int i;
	GBIT_INITDATA InitData;
	char *username, *password;
	char Hostname[32];
	char txt1[32];
	char txt2[32];
	struct TSK_Attrs ta;

	if (bCalled)
		return 1;

	m_EthernetIni = Config::loadFromIni(VIB_Drive[1], "ethernet.ini", "ETHERNET_INI");

	// *** Initialize Ethernet module *************************************
	InitData.IpAddress	  = m_EthernetIni->getValue("IPAddress", "0.0.0.0");	// "0.0.0.0" for DHCP
	InitData.IpSubnetMask = m_EthernetIni->getValue("IpSubnetMask", "255.255.255.0");
	InitData.IpDefaultGw  = m_EthernetIni->getValue("IpDefaultGw", "192.168.115.1");
	InitData.IpDNSServer  = m_EthernetIni->getValue("IpDNSServer", "0.0.0.0");
	InitData.HostName	  = m_EthernetIni->getValue("HostName", m_SerialNumber);
	InitData.DomainName	  = m_EthernetIni->getValue("DomainName", "imago");

	m_IPAdr[0] = 0;
	if (GBIT_Init(-1, &InitData) < 0)
		return -1;

	fdOpenSession(TSK_self());

	// *** Get IP-Address via DHCP ***
	if (!strcmp(InitData.IpAddress, "0.0.0.0"))
	{
		for (i = 0; i < 20; i++)
		{
			VIB_WaitBios(500);
			gethostname(Hostname, 32);
			if (strlen(Hostname) > 0)
				break;
		}
		if (i < 20)
		{
			char HostEntBuf[256];
			HOSTENT *h = (HOSTENT *)HostEntBuf;

			printf("Hostname:   '%s'\n", Hostname);
			gethostbyname(Hostname, HostEntBuf, 256);
			if (h->h_addrtype == AF_INET)
				sprintf(m_IPAdr, "%s", inet_ntoa(*(LPIN_ADDR)h->h_addr ));
		}
	}
	else
	{
		strcpy(m_IPAdr, InitData.IpAddress);
	}
	printf("IP-Address: '%s'\n", m_IPAdr);

	// *** Start FTP-Server ***
	m_pFtp = new Ftp();
	m_pFtp->setMaxConnections(m_EthernetIni->getValue("ftpMaxConnections", (int)10));
	username = m_EthernetIni->getValue("ftpUsername", "username");
	password = m_EthernetIni->getValue("ftpPassword", "password");
	m_pFtp->addUser(username, password, 5, 120);
	m_pFtp->addUser("anonymous", "", 5, 60);

	for (i = VIB_DriveCount - 1; i > 1; i--)
	{
		sprintf(txt1, "%s:/", VIB_GetDeviceName(VIB_Drive[i]));
		sprintf(txt2, "/%s", VIB_GetDeviceName(VIB_Drive[i]));
		m_pFtp->addVirtualDir(username, txt1, txt2, "LRW");
		m_pFtp->addVirtualDir("anonymous", txt1, txt2, "LR");
	
	}
	if (VIB_DriveCount>1)
	{
		sprintf(txt1, "%s:/", VIB_GetDeviceName(VIB_Drive[1]));
		m_pFtp->addVirtualDir(username, txt1, "/", "LRW");
		// User 'anonymous': Uncomment to allow access to /public only
//		VIB_MkDir(VIB_Drive[1], "/public");
//		sprintf(txt1, "%s:/public", VIB_GetDeviceName(VIB_Drive[1]));
		m_pFtp->addVirtualDir("anonymous", txt1, "/", "LR");

		sprintf(txt1, "%s:/", VIB_GetDeviceName(VIB_Drive[0]));
		sprintf(txt2, "/%s", VIB_GetDeviceName(VIB_Drive[0]));
		m_pFtp->addVirtualDir(username, txt1, txt2, "LRW");
		m_pFtp->addVirtualDir("anonymous", txt1, txt2, "LR");
	}
	else
	{
		sprintf(txt1, "%s:/", VIB_GetDeviceName(VIB_Drive[0]));
		m_pFtp->addVirtualDir(username, txt1, "/", "LRW");
		m_pFtp->addVirtualDir("anonymous",txt1, "/", "LR");
	}	

	m_pFtp->start();

	// Add files from memory card to web server (http://<IP>/files/index.html)
	AddWebFolder("/web", "files", false);

	// *** TCP-Display ***
	if (GBIT_InitDisplay(Width, Height, TCP_DISPLAY_PORT, &m_TcpDisplay) < 0)
		return -1;

	GUI_DlgGetCoord = GBIT_GetKoord; // Get coordinates from mouse via GBit

	AddIndexHtml(m_TcpDisplay.width, m_TcpDisplay.height, TCP_DISPLAY_PORT);

// Use PNG or JPEG compression for slow network connections
//	PNG_SetGBitMode();
//	JPEG_SetGBitMode();

	// *** Create display task ***
	ta.priority  = TSK_getpri(TSK_self());
	ta.stack     = 0;
	ta.stacksize = 4096;
	ta.stackseg  = 0;
	ta.environ   = 0;
	ta.name      = "TaskDisplay";
	ta.exitflag  = 0;
	if (m_NetAutoRedraw)
		TSK_create((Fxn)TaskDisplay, &ta, &m_TcpDisplay, pDisplayPic);

	// *** Create broadcast task ***
	ta.priority  = TSK_getpri(TSK_self());
	ta.stack     = 0;
	ta.stacksize = 4096;
	ta.stackseg  = 0;
	ta.environ   = 0;
	ta.name      = "TaskBroadcast";
	ta.exitflag  = 0;
	TSK_create((Fxn)TaskUDPBroadcast, &ta, this);

	bCalled = true;
	return 0;
}

/*************************************************************************/
int CNetwork::AddWebFolder(const char *Folder, const char *DstFolder, bool IsTopDir)
/*************************************************************************/
/*! @brief Add files in folder on the memory card to the web server.
	@param Folder String containing the folder name on the memory card
	@param DstFolder String containing the destination folder on the web server
	@param IsTopDir Destination is top directory
**************************************************************************/
{
	int i, j;
	int result;
	char *files;
	char *IndexHtml;
	char FilePath[256];
	char Filename[256];
	char url[256];
	char text[200];
	FILEINFO FileInfo;

	if (VIB_FindFile2(VIB_Drive[1], Folder) != FAT_DIRECTORY)
		return -1;

	files = (char*)VIB_MemAlloc(10 * 1024);
	IndexHtml = (char*)VIB_MemAlloc(10 * 1024);
	if (files == NULL || IndexHtml == NULL)
		return -1;

	strcpy(files, Folder);
	if (VIB_ReadDirEx(VIB_Drive[1], files, RD_DIR | RD_PATH) < 0)
		return -1;

	sprintf(IndexHtml, "<HTML> <HEAD> <TITLE> - Index of /%s - </TITLE> </HEAD>\r\n", DstFolder);
	strcat(IndexHtml, "<BODY bgcolor=\"#324B64\" link=\"#FFFFFF\" vlink=\"#FFFFFF\" alink=\"#FFFF00\" text=\"#FFFFFF\">\r\n");
	sprintf(text, "<H1>Index of /%s</H1>\r\n", DstFolder);
	strcat(IndexHtml, text);
	if (!IsTopDir)
		strcat(IndexHtml, "<a href=\"../index.html\">..</a><br/>\r\n");

	for (i = 0; files[i] != '\0'; i += 13)
	{
		if (!strncmp(files + i, "..", 2))
			continue;

		// File name without spaces
		memset(Filename, 0, 13);
		for (j = 8; j > 0 && files[i + j - 1] == ' '; j--);
		strncpy(Filename, files + i, j);
		for (j = 4; j > 0 && files[i + j + 7] == ' '; j--);
		strncat(Filename, files + i + 8, j);

		sprintf(FilePath, "%s/", Folder);
		strncat(FilePath, Filename, 12);
		VIB_GetFileInfo(VIB_Drive[1], FilePath, &FileInfo);
		if (FileInfo.LName[0] != '\0')
			strcpy(Filename, FileInfo.LName);
		result = VIB_FindFile2(VIB_Drive[1], FilePath);
		if (result >= 0)
		{
			if (DstFolder[0] == '\0')
				sprintf(url, "%s", DstFolder);
			else
				sprintf(url, "%s/", DstFolder);
//			strncat(url, Filename, 12);
			strcat(url, Filename);
			printf("Adding Web file '%s'\n", url);
			if (AddWebFile(FilePath, url) < 0)
			{
				printf("  Error.\n");
			}
			else
			{
				sprintf(text, "<a href=\"%s\">%s - %d kB</a><br/>\r\n", Filename, Filename, FileInfo.FileSize / 1024);
				strcat(IndexHtml, text);
			}
		}
		else if (result == FAT_DIRECTORY)
		{
			if (DstFolder[0] == '\0')
				sprintf(url, "%s", Filename);
			else
				sprintf(url, "%s/%s", DstFolder, Filename);
			AddWebFolder(FilePath, url, false);
			sprintf(text, "<a href=\"%s/index.html\">/%s</a><br/>\r\n", url, url);
			strcat(IndexHtml, text);
		}
	}

	strcat(IndexHtml, "</BODY> </HTML>\n");
	if (DstFolder[0] == '\0')
		sprintf(url, "index.html");
	else
		sprintf(url, "%s/index.html", DstFolder);
	GBIT_AddWebFile(url, (unsigned char *)IndexHtml, strlen(IndexHtml));

	VIB_MemFree(files);
	VIB_MemFree(IndexHtml);
	return 0;
}

/*************************************************************************/
void CNetwork::Stop()
/*************************************************************************/
/*! @brief Shutdown the network.
**************************************************************************/
{
	m_pFtp->stop();
	GBIT_CloseDisplay(&m_TcpDisplay);
	fdCloseSession(TSK_self());
}

/*************************************************************************/
int CNetwork::AddWebFile(const char *SrcFileName, const char *DstFileName)
/*************************************************************************/
/*! @brief Serves a file from flash card on the web server.
	@param SrcFileName File name of source file on flash card
	@param DstFileName File name of destination file on Ethernet module.
	@return Error code
**************************************************************************/
{
	unsigned char *pFileBuffer;
	int FileSize;
	int result = 0;

	FileSize = VIB_FindFile2(VIB_Drive[1], SrcFileName);
	if (FileSize <= 0)
	{
		printf("'%s' could not be read\n", SrcFileName);
		return -1;
	}
	pFileBuffer = (unsigned char *)VIB_MemAlloc(FileSize);
	VIB_ReadFile(VIB_Drive[1], SrcFileName, pFileBuffer);
	result = GBIT_AddWebFile(DstFileName, pFileBuffer, FileSize);
	if (result < 0)
		printf("GBIT_AddWebFile() failed (%d).\n", result);
	VIB_MemFree(pFileBuffer);
	return result;
}

/*************************************************************************/
void CNetwork::AddIndexHtml(int DisplayWidth, int DisplayHeight, int DisplayPort)
/*************************************************************************/
/*! @brief Creates index file for display via GBit Ethernet. (\p index.html)
	@param DisplayWidth Width of display
	@param DisplayHeight Height of display
	@param DisplayPort TCP port
**************************************************************************/
{
	char *pFileBuffer;
	char text[200];

	pFileBuffer = (char*)VIB_MemAlloc(1024);
	sprintf(pFileBuffer, "<html>\n<head>\n<title>Vision Box - %s</title>\n</head>\n", m_SerialNumber);
	strcat(pFileBuffer, "<body bgcolor=\"#324B64\" link=\"#FFFFFF\" vlink=\"#FFFFFF\" alink=\"#FFFF00\" text=\"#FFFFFF\">");
	strcat(pFileBuffer, "<center>\n<applet code=\"TcpDisplay.class\" archive=\"TcpDisplay.jar\" ");
	sprintf(text, "width=%d height=%d ", DisplayWidth, DisplayHeight);
	strcat(pFileBuffer, text);
	strcat(pFileBuffer, "alt=\"Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason.\">\n");
	sprintf(text, "<param name=\"port\" value=\"%d\">\n", DisplayPort);
	strcat(pFileBuffer, text);
	if (VIB_FindFile2(VIB_Drive[0], "TcpDisp.jar") > 0)
		strcat(pFileBuffer, "<param name=\"jnlp_href\" value=\"TcpDisplay.jnlp\">\n");
	strcat(pFileBuffer, "<param name=\"draggable\" value=\"true\">\n");
	strcat(pFileBuffer, "Your browser is completely ignoring the &lt;APPLET&gt; tag!</applet>\n</center>\n");

	if (m_NetShowLinks)
	{
		strcat(pFileBuffer, "<div>\n");
#ifdef MPS2
		if (GBIT_Version < 809050000)
			strcat(pFileBuffer, "<a href=\"inform.cgi?sockets\" target=\"_clean\">Display socket information</a><br/>\n");
		else
			strcat(pFileBuffer, "<a href=\"stack.cgi\" target=\"_clean\">Display socket information</a><br/>\n");
#endif
		if (m_IPAdr[0] != 0)
		{
			sprintf(text, "<a href=\"ftp://%s\" target=\"_clean\">ftp://%s</a>\n", m_IPAdr, m_IPAdr);
			strcat(pFileBuffer, text);
		}
		strcat(pFileBuffer, "</div>\n");
	}
	strcat(pFileBuffer, "</body>\n</html>\n");
	GBIT_AddWebFile("index.html", (unsigned char*) pFileBuffer, strlen(pFileBuffer));

	// Create "TcpDisplay.jnlp"
	if (m_IPAdr[0] != 0)
	{
		strcpy(pFileBuffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		sprintf(text, "<jnlp spec=\"1.0+\" codebase=\"http://%s/\" href=\"TcpDisplay.jnlp\">\n", m_IPAdr);
		strcat(pFileBuffer, text);
		strcat(pFileBuffer, "<information>\n");
		sprintf(text, "<title>TcpDisplay (%s)</title>\n", m_IPAdr);
		strcat(pFileBuffer, text);
		strcat(pFileBuffer, "<vendor>IMAGO Technologies</vendor>\n"
							"<description kind=\"short\">\n"
							"This Applet enables access to the VisionBox GUI by using a TCP connection.\n"
							"</description>\n"
							"<icon kind=\"shortcut\" href=\"jar:TcpDisplay.jar!/images/strampe.png\"/>\n"
							"<offline-allowed/>\n"
							"<shortcut online=\"false\">\n<desktop />\n</shortcut>\n"
							"</information>\n"
							"<security>\n<all-permissions/>\n</security>\n"
							"<resources><j2se version=\"1.5+\"/><jar href=\"TcpDisplay.jar\"/>\n</resources>\n");
		sprintf(text, "<applet-desc main-class=\"TcpDisplay\" name=\"TcpDisplay\" width=\"%d\" height=\"%d\"/>\n</jnlp>\n", 
			DisplayWidth, DisplayHeight);
		strcat(pFileBuffer, text);
		GBIT_AddWebFile("TcpDisplay.jnlp", (unsigned char*) pFileBuffer, strlen(pFileBuffer));
	}
	VIB_MemFree(pFileBuffer);
}

/*************************************************************************/
int CNetwork::ChangeIpAddr(const char *pIpAddr)
/*************************************************************************/
/*! @brief Change IP-Address in .INI-file.
	@param pIpAddr String with new IP-Address
	@return Error code
**************************************************************************/
{
	if (m_EthernetIni == NULL)
		return -1;
	m_EthernetIni->setValue("IPAddress", pIpAddr);
	m_EthernetIni->saveToIni(VIB_Drive[1], "ethernet.ini");
	return 0;
}

// \}
/*************************************************************************/
