mirror of
https://github.com/bobbimanners/emailler.git
synced 2025-02-21 16:29:06 +00:00
Added HttpFileServer65.
HttpFileServer65 is inspired by "HFS ~ Http File Server" (http://www.rejetto.com/hfs/). It features an intuitive mapping of local disks and directories to HTTP paths. This allows to not only navigate to some file but to directly enter some file URL. This is especially usefull for downloads via wget, curl or alike. However, in contrast to HFS it doesn't allow file uploads, only file downloads. On targets with complete DIO support it additionally allows disk image downloads. Note: The Atari build currently fails as there's so far no getdevicedir() in the Atari C library.
This commit is contained in:
parent
5a1c3fda7e
commit
a07e889d7b
@ -26,6 +26,7 @@ UDP =\
|
||||
date
|
||||
|
||||
TCP =\
|
||||
hfs65 \
|
||||
telnet65
|
||||
|
||||
all: $(UDP) $(TCP)
|
||||
@ -97,11 +98,13 @@ telnet65.com: ATARI_CFG = atrtelnet.cfg
|
||||
ip65.d64: prg
|
||||
$(C1541) -format ip65,00 d64 $@
|
||||
$(C1541) -attach $@ -write date.prg date,p
|
||||
$(C1541) -attach $@ -write hfs65.prg hfs65,p
|
||||
$(C1541) -attach $@ -write telnet65.prg telnet65,p
|
||||
|
||||
ip65.dsk: bin
|
||||
cp prodos.dsk $@
|
||||
java -jar $(AC) -cc65 $@ date bin < date.bin
|
||||
java -jar $(AC) -cc65 $@ hfs65 bin < hfs65.bin
|
||||
java -jar $(AC) -cc65 $@ telnet65 bin < telnet65.bin
|
||||
|
||||
ip65.atr: com
|
||||
|
328
apps/hfs65.c
Normal file
328
apps/hfs65.c
Normal file
@ -0,0 +1,328 @@
|
||||
#include <dio.h>
|
||||
#include <cc65.h>
|
||||
#include <fcntl.h>
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <device.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "../inc/ip65.h"
|
||||
|
||||
#ifdef __CBM__
|
||||
//#define IMAGE ".D64"
|
||||
#endif
|
||||
#ifdef __APPLE2__
|
||||
#define IMAGE ".PO"
|
||||
#endif
|
||||
#ifdef __ATARI__
|
||||
//#define IMAGE ".ATR"
|
||||
#endif
|
||||
|
||||
#define SEND_FIRST 1
|
||||
#define SEND_LAST 2
|
||||
|
||||
unsigned char send_buffer[1024];
|
||||
unsigned int send_size;
|
||||
unsigned char send_type;
|
||||
|
||||
void send(unsigned char flags, const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (flags & SEND_FIRST)
|
||||
{
|
||||
send_size = 0;
|
||||
send_type = HTTPD_RESPONSE_200_HTML;
|
||||
}
|
||||
|
||||
va_start(args, str);
|
||||
send_size += vsnprintf(send_buffer + send_size, sizeof(send_buffer) - send_size, str, args);
|
||||
va_end(args);
|
||||
|
||||
if (flags & SEND_LAST || sizeof(send_buffer) - send_size < 1024 / 4)
|
||||
{
|
||||
#ifdef __CBM__
|
||||
{
|
||||
unsigned char* ptr = send_buffer;
|
||||
unsigned char* end = send_buffer + send_size;
|
||||
|
||||
for (; ptr != end; ++ptr)
|
||||
{
|
||||
*ptr = toascii(*ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
httpd_send_response(send_type, send_buffer, send_size);
|
||||
send_size = 0;
|
||||
send_type = HTTPD_RESPONSE_NOHEADER;
|
||||
}
|
||||
}
|
||||
|
||||
void error(void)
|
||||
{
|
||||
httpd_send_response(HTTPD_RESPONSE_500, 0, 0);
|
||||
printf("500\n");
|
||||
}
|
||||
|
||||
void root(void)
|
||||
{
|
||||
char diskdir[FILENAME_MAX];
|
||||
char* rootdir = diskdir;
|
||||
unsigned char disk = getfirstdevice();
|
||||
|
||||
#ifdef __APPLE2__
|
||||
// skip '/'
|
||||
++rootdir;
|
||||
#endif
|
||||
|
||||
send(SEND_FIRST, "<h2>/</h2><table style='border-spacing: 1em 0em'>");
|
||||
|
||||
while (disk != INVALID_DEVICE)
|
||||
{
|
||||
if (getdevicedir(disk, diskdir, sizeof(diskdir)))
|
||||
{
|
||||
send(0, "<tr><td>Disk</td><td><a href='%s'>%s</a></td></tr>",
|
||||
rootdir, rootdir);
|
||||
|
||||
#ifdef IMAGE
|
||||
{
|
||||
dhandle_t dio = dio_open(disk);
|
||||
if (dio)
|
||||
{
|
||||
send(0, "<tr><td>Image</td><td><a href='%s"IMAGE"'>%s"IMAGE"</a></td><td align=right>%u</td></tr>",
|
||||
rootdir, rootdir, dio_query_sectcount(dio));
|
||||
dio_close(dio);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
disk = getnextdevice(disk);
|
||||
}
|
||||
send(SEND_LAST, "</table>");
|
||||
|
||||
printf("200\n");
|
||||
}
|
||||
|
||||
void directory(const char* path)
|
||||
{
|
||||
char* delimiter;
|
||||
struct dirent *ent;
|
||||
DIR *dir = opendir(".");
|
||||
|
||||
if (!dir)
|
||||
{
|
||||
error();
|
||||
return;
|
||||
}
|
||||
|
||||
send(SEND_FIRST, "<h2>%s</h2><table style='border-spacing: 1em 0em'>", path);
|
||||
|
||||
delimiter = strrchr(path, '/');
|
||||
if (delimiter && delimiter != path)
|
||||
{
|
||||
*delimiter = '\0';
|
||||
send(0, "<tr><td>Directory</td><td><a href='%s'>..</a></td></tr>", path);
|
||||
*delimiter = '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
send(0, "<tr><td>Disk</td><td><a href='/'>..</a></td></tr>");
|
||||
}
|
||||
|
||||
while (ent = readdir(dir))
|
||||
{
|
||||
if (_DE_ISREG(ent->d_type))
|
||||
{
|
||||
#ifdef __ATARI__
|
||||
send(0, "<tr><td>File</td><td><a href='%s/%s'>%s</a></td></tr>",
|
||||
path, ent->d_name, ent->d_name);
|
||||
#else
|
||||
send(0, "<tr><td>File</td><td><a href='%s/%s'>%s</a></td><td align=right>%u</td></tr>",
|
||||
path, ent->d_name, ent->d_name, ent->d_blocks);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (_DE_ISDIR(ent->d_type))
|
||||
{
|
||||
send(0, "<tr><td>Directory</td><td><a href='%s/%s'>%s</a></td></tr>",
|
||||
path, ent->d_name, ent->d_name);
|
||||
}
|
||||
}
|
||||
send(SEND_LAST, "</table>");
|
||||
|
||||
closedir(dir);
|
||||
printf("200\n");
|
||||
}
|
||||
|
||||
unsigned char file(const char* name)
|
||||
{
|
||||
int size;
|
||||
int file = open(name, O_RDONLY);
|
||||
|
||||
if (file < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
send_type = HTTPD_RESPONSE_200_DATA;
|
||||
while ((size = read(file, send_buffer, sizeof(send_buffer))) > 0)
|
||||
{
|
||||
httpd_send_response(send_type, send_buffer, size);
|
||||
send_type = HTTPD_RESPONSE_NOHEADER;
|
||||
}
|
||||
|
||||
close(file);
|
||||
printf("200\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef IMAGE
|
||||
void image()
|
||||
{
|
||||
unsigned int sector = 0;
|
||||
dhandle_t dio = dio_open(getcurrentdevice());
|
||||
|
||||
if (!dio)
|
||||
{
|
||||
error();
|
||||
return;
|
||||
}
|
||||
|
||||
send_size = dio_query_sectsize(dio);
|
||||
send_type = HTTPD_RESPONSE_200_DATA;
|
||||
|
||||
#ifdef __ATARI__
|
||||
#error "TODO: Send ATR header."
|
||||
dio_query_sectcount(dio);
|
||||
#endif
|
||||
|
||||
while (!dio_read(dio, sector++, send_buffer))
|
||||
{
|
||||
httpd_send_response(send_type, send_buffer, send_size);
|
||||
send_type = HTTPD_RESPONSE_NOHEADER;
|
||||
}
|
||||
|
||||
dio_close(dio);
|
||||
printf("200\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void http_server(unsigned long client, const char* method, const char* path)
|
||||
{
|
||||
char* delimiter;
|
||||
|
||||
printf("%s \"%s %s\" ", dotted_quad(client), method, path);
|
||||
|
||||
if (stricmp(method, "get") || path[0] != '/')
|
||||
{
|
||||
error();
|
||||
return;
|
||||
}
|
||||
|
||||
if (path[1] == '\0')
|
||||
{
|
||||
root();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef __APPLE2__
|
||||
// skip '/'
|
||||
++path;
|
||||
#endif
|
||||
|
||||
if (!chdir(path))
|
||||
{
|
||||
directory(path);
|
||||
return;
|
||||
}
|
||||
|
||||
delimiter = strrchr(path, '/');
|
||||
if (delimiter && delimiter != path)
|
||||
{
|
||||
*delimiter++ = '\0';
|
||||
if (!chdir(path) && file(delimiter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef IMAGE
|
||||
else
|
||||
{
|
||||
delimiter = strrchr(path, '.');
|
||||
if (delimiter)
|
||||
{
|
||||
*delimiter = '\0';
|
||||
if (!chdir(path))
|
||||
{
|
||||
image();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
httpd_send_response(HTTPD_RESPONSE_404, 0, 0);
|
||||
printf("404\n");
|
||||
}
|
||||
|
||||
void error_exit(void)
|
||||
{
|
||||
switch (ip65_error)
|
||||
{
|
||||
case IP65_ERROR_DEVICE_FAILURE:
|
||||
printf("- No device found\n");
|
||||
break;
|
||||
case IP65_ERROR_ABORTED_BY_USER:
|
||||
printf("- User abort\n");
|
||||
break;
|
||||
case IP65_ERROR_TIMEOUT_ON_RECEIVE:
|
||||
printf("- Timeout\n");
|
||||
break;
|
||||
default:
|
||||
printf("- Error $%X\n", ip65_error);
|
||||
}
|
||||
|
||||
if (doesclrscrafterexit())
|
||||
{
|
||||
printf("\nPress any key ");
|
||||
cgetc();
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
char cwd[FILENAME_MAX];
|
||||
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
|
||||
#ifdef __APPLE2__
|
||||
videomode(VIDEOMODE_80COL);
|
||||
#endif
|
||||
|
||||
printf("\nHttpFileServer65 v1.0"
|
||||
"\n====================="
|
||||
"\n\nInitializing ");
|
||||
if (ip65_init())
|
||||
{
|
||||
error_exit();
|
||||
}
|
||||
|
||||
printf("- Ok\n\nObtaining IP address ");
|
||||
if (dhcp_init())
|
||||
{
|
||||
error_exit();
|
||||
}
|
||||
|
||||
printf("- Ok\n\nStarting server on %s\n\n", dotted_quad(cfg_ip));
|
||||
httpd_start(80, http_server);
|
||||
|
||||
chdir(cwd);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user