/*******************************************************************************
        static2.c
        Z-World, 2000

        Similar to static.c, this program serves up basic statis
        web pages, but integrates the ftp server to allow you to
        change the pages at runtime.  This is a max size for file.

        Starting in 7.30, if an FTP handler function is NULL, the
        default handler will be used instead.

   Sample HTTP + FTP daemon.

   To use:
	      Edit IP/netmask/etc in "LIB\TCPIP\TCP_CONFIG.LIB"
   	   Compile/Run it.
	      Browse to it with netscape, and note the default index.html page.
   	   FTP to it, and upload a file called 'index.html'
      	Browse to it again with netscape, and your file will have
         		replaced the default index.html

*******************************************************************************/
/*
 * 	By default, have compiler make function variables storage class
 * 	"auto" (allocated on the stack).
 */
#class auto

 
/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 * Pick the predefined TCP/IP configuration for this sample.  See
 * LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
 * configuration.
 */
#define TCPCONFIG 1


/*
 * TCP/IP modification - reduce TCP socket buffer
 * size, to allow more connections. This can be increased,
 * with increased performance, if the number of sockets
 * are reduced.  Note that this buffer size is split in
 * two for TCP sockets--1024 bytes for send and 1024 bytes
 * for receive.
 */
#define TCP_BUF_SIZE 2048

/*
 * Web server configuration
 */

/*
 * Only one server is needed when using a reserved port
 */
#define HTTP_MAXSERVERS 1

/*
 * Define this if you do not need to use the http_flashspec array.
 * Since this program uses only the ZSERVER.LIB functionality,
 * then it does not need the http_flashspec array.
 */
#define HTTP_NO_FLASHSPEC

/*
 * Set the maximum number of sockets to use.  We have set the HTTP
 * server to use 1 socket, and the FTP server uses 2 sockets.
 */
#define MAX_TCP_SOCKET_BUFFERS 3

/*
 * 	Allow writing to files with FTP server.  This allows FTP directory
 * 	listings to show write access.
 */
#define FTP_WRITABLE_FILES 1


/********************************
 * End of configuration section *
 ********************************/

// #define FTP_DEBUG

/*
 * FTP configuration - you shouldn't have to change this
 */
/* maximum size of a file we can receive for 'index.html' */
#define MAX_NEWFILESIZE	0x4000


#memmap xmem
#use "dcrtcp.lib"
#use "http.lib"
#use "ftp_server.lib"

#ximport "samples/tcpip/http/pages/rabbit1.gif"    rabbit1_gif
#ximport "samples/tcpip/http/pages/static.html"  index_html

/* the default mime type for '/' must be first */
const HttpType http_types[] =
{
   { ".html", "text/html", NULL},
   { ".gif", "image/gif", NULL}
};

/* storage for the new file */
long newfile;
long newfilesize;
int newuser;

/* handlers for ftp */
int ftp_handlers_open(char *name, int options, int uid);
long ftp_handlers_getfilesize(int fd);
int ftp_handlers_read(int fd, char *buf, long offset, int len);
int ftp_handlers_write(int fd, char *buf, long offset, int len);
int ftp_handlers_close(int fd);
int ftp_handlers_list(int item, char *line, int listing);


/*
 * 	Starting in 7.30, if the handler is left NULL, the default is
 * 	pulled in.  This means Z-World can extend this list, you
 * 	recompile, and new fetures automagically appear!
 */
const FTPhandlers ftp_file_handlers = {
	ftp_handlers_open,
	ftp_handlers_read,
	ftp_handlers_write,
	ftp_handlers_close,
	NULL, 		// USE DEFAULT: getfilesize,
	NULL 			//	USE DEFAULT: list
};


void main()
{
	int file;
	int user;

	// Set up the anonymous user
	user = sauth_adduser("anonymous", "", SERVER_FTP | SERVER_WRITABLE );
	sauth_setwriteaccess(user, 1);
	ftp_set_anonymous(user);

	// Add index.html
	file = sspec_addxmemfile("index.html", index_html,
										SERVER_HTTP | SERVER_FTP | SERVER_WRITABLE);
	sspec_setuser(file, user);

	// Add this entry, so that index_html is the default page
	sspec_addxmemfile("/", index_html, SERVER_HTTP);

	// Add rabbit1.gif
	file = sspec_addxmemfile("rabbit1.gif", rabbit1_gif, SERVER_HTTP | SERVER_FTP);
	sspec_setuser(file, user);

	// Set up the foo user
	user = sauth_adduser("foo", "bar", SERVER_FTP);
	sauth_setwriteaccess(user, 1);

	// Allocate space for file. First four bytes is length.  Each upload
	//  overwrites the previous contents.
	newfile = xalloc(MAX_NEWFILESIZE + 4);
	if(0 == newfile) {
		exit(0);
	}
	
	sock_init();
	http_init();
	ftp_init(&ftp_file_handlers);
	tcp_reserveport(80); //reserve port for HTTP server

	while(1) {
		http_handler();
		ftp_tick();
	}
}


/*******************************
 * The FTP read/write handlers *
 *******************************/

int ftp_handlers_open(char *name, int options, int uid)
{
	if( options != O_WRONLY ) {
		/* unsupported mode at this time */
		return FTP_ERR_BADMODE;
	}

	if(strncmp(name,"index.html", 10)) {
		/* not index.html */
		return FTP_ERR_NOTAUTH;
	}
	
	sspec_remove(sspec_findname("/", SERVER_HTTP));
	sspec_remove(sspec_findname("index.html", SERVER_HTTP));
	newuser = uid;

	newfilesize = 4;
	
	return 0;
}

int ftp_handlers_read(int fd, char *buf, long offset, int len)
{
	/* should never come here - we don't support reading in this handler */
	return 0;
}

int ftp_handlers_write(int fd, char *buf, long offset, int len)
{
	auto int wlen, i;

	if(0 != fd) {
		/* bad fd */
		return -1;
	}
	
	/* find write length */
	wlen = (MAX_NEWFILESIZE + 4) - (int)offset;
	if(wlen > len) wlen = len;

	root2xmem(newfile + offset + 4, buf, wlen);
	newfilesize += wlen;

	return wlen;
}

int ftp_handlers_close(int fd)
{
	int file;

	newfilesize -= 4;

	root2xmem(newfile, &newfilesize, 4);

	file = sspec_addxmemfile("index.html", newfile, SERVER_HTTP | SERVER_FTP | SERVER_WRITABLE);
	sspec_setuser(file, newuser);

	sspec_addxmemfile("/", newfile, SERVER_HTTP);

	return 0;
}

/* Use FTP server defaults for file size and directory listing. */
