| Current Path : /var/www/html/mmishra/nweb/ |
| Current File : /var/www/html/mmishra/nweb/icdp.c |
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define VERSION 23
#define BUFSIZE 8096
//#define BUFSIZE 1024
#define ERROR 42
#define LOG 44
#define FORBIDDEN 403
#define NOTFOUND 404
void filter_tag(char *);
char httpbuffer[BUFSIZE+1];
long httplen = 0;
#ifndef SIGCLD
# define SIGCLD SIGCHLD
#endif
struct {
char *ext;
char *filetype;
} extensions [] = {
{"gif", "image/gif" },
{"jpg", "image/jpg" },
{"jpeg","image/jpeg"},
{"png", "image/png" },
{"ico", "image/ico" },
{"zip", "image/zip" },
{"gz", "image/gz" },
{"tar", "image/tar" },
{"htm", "text/html" },
{"html","text/html" },
{0,0} };
//by jatin mehta & aditya chaturvedi
struct tm *current_date, *catched_date;
int dateisexpired(struct tm *t) {
if(current_date -> tm_year < t -> tm_year)
return 0;
if(current_date -> tm_year > t -> tm_year)
return 1;
if(current_date -> tm_mon < t -> tm_mon)
return 0;
if(current_date -> tm_mon > t -> tm_mon)
return 1;
if(current_date -> tm_mday < t -> tm_mday)
return 0;
if(current_date -> tm_mday > t -> tm_mday)
return 1;
return 0;
}
int start_tag(int x) {
while(x >= 0 && httpbuffer[x] != '<'){
//printf("%c",httpbuffer[x--]);
x--;
}
return x;
}
int end_tag(int x) {
int open = 1;
int close = 0;
while(x < httplen) {
if(httpbuffer[x] == '<') {
int check = 0;
while(x < httplen && httpbuffer[x] != '>') {
if(httpbuffer[x] == '<' && httpbuffer[x+1] == '/') { check = 1;
}
x++;
}
if(check) {
close++;
}else{
open++;
}
if(open == close) {
return (x);
}
}
x++;
}
//printf("someting worng happend :( \n");
while(1);
}
void del_tag(int x, int y) {
//printf("removed tag : ");
for(; x <= y; x++) {
//printf("%c",httpbuffer[x]);
httpbuffer[x] = ' ';
}
//printf("\n");
}
void filter_tag(char str[]) {
int i = 0;
while(i < httplen) {
//printf("%d \n",i);
if(httpbuffer[i] == str[0]) {
int j = i;
int k = 0;
int check = 0;
while(j < httplen && str[k] != '\0') {
if(str[k] != httpbuffer[j]) {
check = 1;
break;
}
j++;
k++;
}
if(!check) {
int ax;
int date[8];
ax = j + 2;
//Assuming date format as exp="dd/mm/yyyy"
date[0] = (int)httpbuffer[ax] - 48;
date[1] = (int)httpbuffer[ax+1] - 48;
date[2] = (int)httpbuffer[ax+3] - 48;
date[3] = (int)httpbuffer[ax+4] - 48;
date[4] = (int)httpbuffer[ax+6] - 48;
date[5] = (int)httpbuffer[ax+7] - 48;
date[6] = (int)httpbuffer[ax+8] - 48;
date[7] = (int)httpbuffer[ax+9] - 48;
//Catched_date contains the date extracted from the HTML.
catched_date = (struct tm *)malloc(sizeof(struct tm));
catched_date -> tm_mday = (date[0] * 10) + date[1];
catched_date -> tm_mon = (date[2] * 10) + date[3];
catched_date -> tm_year = (date[4] * 1000) + (date[5] * 100) + (date[6] * 10) + date[7];
if(dateisexpired(catched_date)) {
int start = start_tag(i);
int end = end_tag(j);
del_tag(start,end);
}
}
}
i++;
}
}
void logger(int type, char *s1, char *s2, int socket_fd) {
int fd ;
char logbuffer[BUFSIZE*2];
switch (type) {
case ERROR:
(void)sprintf(logbuffer,"ERROR: %s:%s Errno=%d exiting pid=%d",s1, s2, errno,getpid());
break;
case FORBIDDEN:
(void)write(socket_fd, "HTTP/1.1 403 Forbidden\nContent-Length: 185\nConnection: close\nContent-Type: text/html\n\n<html><head>\n<title>403 Forbidden</title>\n</head><body>\n<h1>Forbidden</h1>\nThe requested URL, file type or operation is not allowed on this simple static file webserver.\n</body></html>\n",271);
(void)sprintf(logbuffer,"FORBIDDEN: %s:%s",s1, s2);
break;
case NOTFOUND:
(void)write(socket_fd, "HTTP/1.1 404 Not Found\nContent-Length: 136\nConnection: close\nContent-Type: text/html\n\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\nThe requested URL was not found on this server.\n</body></html>\n",224);
(void)sprintf(logbuffer,"NOT FOUND: %s:%s",s1, s2);
break;
case LOG:
(void)sprintf(logbuffer," INFO: %s:%s:%d",s1, s2,socket_fd);
break;
}
/* No checks here, nothing can be done with a failure anyway */
if((fd = open("nweb.log", O_CREAT| O_WRONLY | O_APPEND,0644)) >= 0) {
(void)write(fd,logbuffer,strlen(logbuffer));
(void)write(fd,"\n",1);
(void)close(fd);
}
if(type == ERROR || type == NOTFOUND || type == FORBIDDEN) exit(3);
}
/* this is a child web server process, so we can exit on errors */
void web(int fd, int hit) {
int j, file_fd, buflen;
long i, ret, len;
char * fstr;
static char buffer[BUFSIZE+1]; /* static so zero filled */
ret = read(fd,buffer,BUFSIZE); /* read Web request in one go */
if(ret == 0 || ret == -1) { /* read failure stop now */
logger(FORBIDDEN,"failed to read browser request","",fd);
}
if(ret > 0 && ret < BUFSIZE) /* return code is valid chars */
buffer[ret]=0; /* terminate the buffer */
else buffer[0]=0;
for(i=0;i<ret;i++) /* remove CF and LF characters */
if(buffer[i] == '\r' || buffer[i] == '\n')
buffer[i]='*';
logger(LOG,"request",buffer,hit);
if( strncmp(buffer,"GET ",4) && strncmp(buffer,"get ",4) ) {
logger(FORBIDDEN,"Only simple GET operation supported",buffer,fd);
}
for(i=4;i<BUFSIZE;i++) { /* null terminate after the second space to ignore extra stuff */
if(buffer[i] == ' ') { /* string is "GET URL " +lots of other stuff */
buffer[i] = 0;
break;
}
}
for(j=0;j<i-1;j++) /* check for illegal parent directory use .. */
if(buffer[j] == '.' && buffer[j+1] == '.') {
logger(FORBIDDEN,"Parent directory (..) path names not supported",buffer,fd);
}
if( !strncmp(&buffer[0],"GET /\0",6) || !strncmp(&buffer[0],"get /\0",6) ) /* convert no filename to index file */
(void)strcpy(buffer,"GET /index.html");
/* work out the file type and check we support it */
buflen=strlen(buffer);
fstr = (char *)0;
for(i=0;extensions[i].ext != 0;i++) {
len = strlen(extensions[i].ext);
if( !strncmp(&buffer[buflen-len], extensions[i].ext, len)) {
fstr =extensions[i].filetype;
break;
}
}
if(fstr == 0) logger(FORBIDDEN,"file extension type not supported",buffer,fd);
if(( file_fd = open(&buffer[5],O_RDONLY)) == -1) { /* open the file for reading */
logger(NOTFOUND, "failed to open file",&buffer[5],fd);
}
logger(LOG,"SEND",&buffer[5],hit);
/* lseek to the file end to find the length */
len = (long)lseek(file_fd, (off_t)0, SEEK_END);
/* lseek back to the file start ready for reading */
(void)lseek(file_fd, (off_t)0, SEEK_SET);
(void)sprintf(buffer,"HTTP/1.1 200 OK\nServer: nweb/%d.0\nContent-Length: %ld\nConnection: close\nContent-Type: %s\n\n", VERSION, len, fstr); /* Header + a blank line */
logger(LOG,"Header",buffer,hit);
(void)write(fd,buffer,strlen(buffer));
/* send file in 1KB block - last block may be smaller */
while ( (ret = read(file_fd, buffer, BUFSIZE)) > 0 ) {
for (i=0; i<ret; i++) {
httpbuffer[i] = buffer[i];
}
httplen = ret;
filter_tag("expDate");
httplen = strlen(httpbuffer);
(void)write(fd,httpbuffer,httplen);
logger(LOG,"Body",httpbuffer,httplen);
}
sleep(1); /* allow socket to drain before signalling the socket is closed */
close(fd);
exit(1);
}
int main(int argc, char **argv) {
int i, port, pid, listenfd, socketfd, hit;
socklen_t length;
static struct sockaddr_in cli_addr; /* static = initialised to zeros */
static struct sockaddr_in serv_addr; /* static = initialised to zeros */
//Finding current time. Declared Global. Required <time.h> header file.
time_t now = time(NULL);
current_date = localtime(&now);
current_date -> tm_mon = current_date -> tm_mon+1 ;
current_date -> tm_year = current_date -> tm_year+1900;
if( argc < 3 || argc > 3 || !strcmp(argv[1], "-?") ) {
(void)printf("hint: nweb Port-Number Top-Directory\t\tversion %d\n\n"
"\tnweb is a small and very safe mini web server\n"
"\tnweb only servers out file/web pages with extensions named below\n"
"\t and only from the named directory or its sub-directories.\n"
"\tThere is no fancy features = safe and secure.\n\n"
"\tExample: nweb 8181 /home/nwebdir &\n\n"
"\tOnly Supports:", VERSION);
for(i=0;extensions[i].ext != 0;i++)
(void)printf(" %s",extensions[i].ext);
(void)printf("\n\tNot Supported: URLs including \"..\", Java, Javascript, CGI\n"
"\tNot Supported: directories / /etc /bin /lib /tmp /usr /dev /sbin \n"
"\tNo warranty given or implied\n\tNigel Griffiths nag@uk.ibm.com\n" );
exit(0);
}
if( !strncmp(argv[2],"/" ,2 ) || !strncmp(argv[2],"/etc", 5 ) ||
!strncmp(argv[2],"/bin",5 ) || !strncmp(argv[2],"/lib", 5 ) ||
!strncmp(argv[2],"/tmp",5 ) || !strncmp(argv[2],"/usr", 5 ) ||
!strncmp(argv[2],"/dev",5 ) || !strncmp(argv[2],"/sbin",6) ){
(void)printf("ERROR: Bad top directory %s, see nweb -?\n",argv[2]);
exit(3);
}
if(chdir(argv[2]) == -1){
(void)printf("ERROR: Can't Change to directory %s\n",argv[2]);
exit(4);
}
/* Become deamon + unstopable and no zombies children (= no wait()) */
if(fork() != 0)
return 0; /* parent returns OK to shell */
(void)signal(SIGCLD, SIG_IGN); /* ignore child death */
(void)signal(SIGHUP, SIG_IGN); /* ignore terminal hangups */
for(i=0;i<32;i++)
(void)close(i); /* close open files */
(void)setpgrp(); /* break away from process group */
logger(LOG,"nweb starting",argv[1],getpid());
/* setup the network socket */
if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0)
logger(ERROR, "system call","socket",0);
port = atoi(argv[1]);
if(port < 1024 || port >60000)
logger(ERROR,"Invalid port number (try 1->60000)",argv[1],0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0)
logger(ERROR,"system call","bind",0);
if( listen(listenfd,64) <0)
logger(ERROR,"system call","listen",0);
for(hit=1; ;hit++) {
length = sizeof(cli_addr);
if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0)
logger(ERROR,"system call","accept",0);
if((pid = fork()) < 0) {
logger(ERROR,"system call","fork",0);
}
else {
if(pid == 0) { /* child */
(void)close(listenfd);
web(socketfd,hit); /* never returns */
} else { /* parent */
(void)close(socketfd);
}
}
}
}