[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Documentation server



 This is an example of a WWW server dedicated to serve documentation
files...
 It's fast. I don't know if it is safe, but since it's only 3kb of source
code is shouldn't be so hard to make it safe.

 I think that using a server gives us much more flexibility...

-- 
Nicolás Lichtmaier.-
#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

typedef struct 
{
	char *ext;
	char *mimetype;
} filetype;

filetype types[] =
{
	{"txt","text/plain"},
	{"html","text/html"},
	{"htm","text/html"},
	{"gif","image/gif"},
	{"jpg","image/jpeg"},
	{"png","image/png"},
	{"ps","application/postcript"},
	{NULL,NULL}
};

void error(int code, const char *msg)
{
	printf("HTTP/1.0 %d Error\n"
	"Content-type: text/html\n\n"
	"<title>%s</title><body><h1>%s</h1></body>\n",code,msg,msg);
	exit(0);
}

int valid(const char *s)
{
	for(;*s & *(s+1);s++)
	{
		if(*s=='.' && *(s+1)=='.')
			return 0;
	}
	return 1;
}

char *days[] = {
	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

char *months[] = {
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

char *gettime(time_t a)
{
	static char out[ 44 ];
	struct tm *t;
	
	t=gmtime(&a);
	
	/* Format:  Day, 01 Mon 1999 01:01:01 GMT */
	
	sprintf( out, "%s, %02i %s %04i %02i:%02i:%02i GMT",
		days[t->tm_wday], t->tm_mday, months[ t->tm_mon ], t->tm_year + 1900,
		t->tm_hour, t->tm_min, t->tm_sec
	);

	return out;
}

int main()
{
	char q[100],*query,fn[120],*ce=NULL;
	int uncompress=0;
	int t=0;
	FILE *f;
	
	query=q;
	fgets(query,100,stdin);
	do fgets(fn,100,stdin); while(fn[0]!='\n' && fn[0]!='\r');
	if (!strncmp(query,"GET /doc",4))
	{
		int i;
		char *p,*q;
		struct stat st;
		
		query+=4;
		p=strchr(query,' ');
		if(!p)
			error(400,"error");
		*p=0;
		snprintf(fn,100,"/usr%s",query);
		if (!valid(fn))
			error(403,"error");
		q=strrchr(fn,'/');
		if (q && !*(q+1))
			strcat(fn,"index.html");
		p=strrchr(fn,'.');
		if(p>q && !strcasecmp(p+1,"gz"))
		{
			ce="gzip";
			if (p>fn)
			{
				p--;
				while(p>fn && *p!='.') p--;
				if (p==fn && *p!='.') p=NULL; 
			}
			else
				p=NULL;
		}
		if (p)
		{
			for (i=0;types[i].ext;i++)
				if(!strcasecmp(types[i].ext,p+1))
					t=i;
		}
		f=fopen(fn,"r");
		if (!f)
		{
			FILE *g;
			int z[2];
			uncompress=1;
			strcat(fn,".gz");
			g=fopen(fn,"r");
			if (!g)
				error(404,"The requested file was not found.");
			fstat(fileno(g),&st);
			if (!S_ISREG(st.st_mode)) error(403,"error");
			pipe(z);
			if (!fork())
			{
				close(z[0]);
				dup2(fileno(g),0);
				dup2(z[1],1);
				dup2(z[1],2);
				execl("/bin/gzip","/bin/gzip","-dc",fn,NULL);
				exit(0);
			}
			close(z[1]);
			fclose(g);
			f=fdopen(z[0],"r");
				
		} else
		{
			fstat(fileno(f),&st);
			if (!S_ISREG(st.st_mode)) error(403,"error");
		}
			
		printf("HTTP/1.0 200 OK\nContent-type: %s\n",types[t].mimetype);
		if (ce)
			printf("Content-Encoding: %s\n",ce);
		if (!uncompress)
		{
			printf("Content-Length: %lu\n",st.st_size);
		}
		printf("Last-Modified: %s\n",gettime(st.st_mtime));
		putchar('\n');
		while(!feof(f))
		{
			char buf[4096];
			i=fread(buf,1,4096,f);
			fwrite(buf,1,i,stdout);
		}
		fclose(f);
		return 0;
	}
	error(strncmp(q,"GET ",4)?405:403,"error");
	return 0;
}

Reply to: