/* Monkey HTTP Daemon * ------------------ * Copyright (C) 2001-2003, Eduardo Silva P. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #define __USE_XOPEN #include #include "monkey.h" /* Sending file... */ int SendFile(int socket, char *pathfile, int ranges[2]) { long int num_bytes , offset_range=0; int st_status=0; char buffer[BUFFER_SOCKET]; FILE *file_request; if((file_request=fopen(pathfile,"r"))==NULL) return -1; if(config->resume==VAR_ON){ /* yyy- */ if(ranges[0]>=0 && ranges[1]==-1){ if(fseek(file_request, ranges[0], SEEK_SET)<0) return -1; } /* yyy-xxx */ if(ranges[0]>=0 && ranges[1]>=0){ if(fseek(file_request, ranges[0], SEEK_SET)<0) return -1; offset_range = (unsigned int) (ranges[1] - ranges[0]) + 1; } /* -xxx */ if(ranges[0]==-1 && ranges[1]>=0){ struct stat buf; if(stat(pathfile, &buf)==0){ if(fseek( file_request, (buf.st_size - ranges[1] ), SEEK_SET)<0) return -1; } } } while((num_bytes=fread(buffer,1, BUFFER_SOCKET, file_request)) > 0 ){ if( num_bytestimeout, ST_SEND); if(config->resume==VAR_ON && offset_range>0) offset_range = (unsigned int ) offset_range - num_bytes; } else { num_bytes = offset_range; st_status=Socket_Timeout(socket, buffer, num_bytes, config->timeout, ST_SEND); break; } if(st_status==-2){ fclose(file_request); return -2; } } fclose(file_request); return 0; } /* It's an valid directory ? */ int CheckDir(char *pathfile) { struct stat path; if(stat(pathfile,&path)==-1) return -1; if(!(path.st_mode & S_IFDIR)) return -1; return 0; } /* It's a normal file ? */ int CheckFile(char *pathfile) { struct stat path; if(stat(pathfile,&path)==-1) return -1; if(!(path.st_mode & S_IFREG)) return -1; return 0; } /* Checking read access Written by Carlos Oliva (carlos.oliva@igloo.cl) */ int AccessFile(char *pathfile) { struct stat file; if(stat(pathfile,&file)==-1) return -1; if( (file.st_mode & S_IRUSR && file.st_uid == geteuid()) || (file.st_mode & S_IRGRP && file.st_gid == getegid()) || (file.st_mode & S_IROTH)) return 0; return -1; /* I can't read it */ } /* Permisos de ejecucion */ int ExecFile(char *pathfile) { struct stat file; if(stat(pathfile,&file)==-1) return -1; if( (file.st_mode & S_IXUSR && file.st_uid == geteuid()) || (file.st_mode & S_IXGRP && file.st_gid == getegid()) || (file.st_mode & S_IXOTH)) return 0; return -1; /* No se puede leer */ } /* Compara 2 strings sin importar Mayusculas ni minusculas */ char *strstr2(char *s, char *t) { static char res[MAX_REQUEST_BODY]; int i, j, k; for (i=0; s[i] ; i++) { for (j=i, k=0; t[k] && toupper(s[j]) == toupper(t[k]); j++, k++) ; if (k > 0 && t[k] == '\0') { for (j=i, k=0; s[j]; j++, k++) res[k] = s[j]; res[k] = s[j]; return (char *) res; } } return NULL; } /* Devuelve la fecha para enviarla en el header */ char *PutDate_string(time_t date) { static char date_gmt[255]; struct tm *gmt_tm; if(date==0){ if ( (date = time(NULL)) == -1 ){ return 0; } } gmt_tm = (struct tm *) gmtime(&date); strftime(date_gmt,255, DATEFORMAT, gmt_tm); return (char *) date_gmt; } time_t PutDate_unix(char *date) { time_t new_unix_time; struct tm t_data; // t_data = M_malloc(sizeof(struct tm)); if(!strptime(date, DATEFORMAT, (struct tm *) &t_data)){ return -1; } new_unix_time = mktime((struct tm *) &t_data); return (new_unix_time); } /* Envia buffer de parametros pasados por *format a traves del descriptor fd. Funcion escrita por Waldo (fatwaldo@yahoo.com) */ int fdprintf(int fd, int type, const char *format, ...) { va_list ap; int length, status; char *buffer = 0; static size_t alloc = 0; if(!buffer) { buffer = (char *)M_malloc(256); if(!buffer) return -1; alloc = 256; } va_start(ap, format); length = vsnprintf(buffer, alloc, format, ap); if(length == alloc - 1) { /* glibc 2.0 */ do { char *ptr; ptr = M_realloc(buffer, alloc + 256); if(!ptr) { length = -1; break; } buffer = ptr; alloc += 256; length = vsnprintf(buffer, alloc, format, ap); } while(length == alloc - 1); } else if(length >= alloc) { char *ptr; /* glibc 2.x, x > 0 */ ptr = M_realloc(buffer, length + 1); if(!ptr) { va_end(ap); return -1; } buffer = ptr; alloc = length + 1; length = vsnprintf(buffer, alloc, format, ap); } va_end(ap); if(length<0){ return -1; } if(type==CHUNKED) status = fdchunked(fd, buffer, length); else status = Socket_Timeout(fd, buffer, length, config->timeout, ST_SEND); M_free(buffer); return status; } /* Envia datos a traves de un socket con transferencia de tipo 'chunked' */ int fdchunked(int fd, char *data, int length) { int lenhexlen, st_status; char hexlength[10]; char *buffer=0; snprintf(hexlength, 10, "%x\r\n", length); lenhexlen=strlen(hexlength); buffer = M_malloc(lenhexlen + length + 3); memset(buffer,'\0', sizeof(buffer)); memcpy(buffer, hexlength, lenhexlen); memcpy(buffer+lenhexlen, data, length); if((st_status=Socket_Timeout(fd, buffer, lenhexlen+length, config->timeout, ST_SEND))<0){ M_free(buffer); return st_status; } if((st_status=Socket_Timeout(fd, "\r\n", 2, 1, ST_SEND))<0){ M_free(buffer); return st_status; } M_free(buffer); return 0; } char *m_build_buffer(const char *format, ...) { va_list ap; int length; char *buffer = NULL; static size_t alloc = 0; if(!buffer) { buffer = (char *)M_malloc(256); if(!buffer) return NULL; alloc = 256; } va_start(ap, format); length = vsnprintf(buffer, alloc, format, ap); if(length == alloc - 1) { /* glibc 2.0 */ do { char *ptr; ptr = M_realloc(buffer, alloc + 256); if(!ptr) { length = -1; break; } buffer = ptr; alloc += 256; length = vsnprintf(buffer, alloc, format, ap); } while(length == alloc - 1); } else if(length >= alloc) { char *ptr; /* glibc 2.x, x > 0 */ ptr = M_realloc(buffer, length + 1); if(!ptr) { va_end(ap); return NULL; } buffer = ptr; alloc = length + 1; length = vsnprintf(buffer, alloc, format, ap); } va_end(ap); if(length<0){ return NULL; } buffer[length]='\0'; return (char * ) buffer; } char *m_build_buffer_from_buffer(char *buffer, const char *format, ...) { va_list ap; int length; char *new_buffer=0; char *buffer_content=0; static size_t alloc = 0; new_buffer = (char *)M_malloc(256); if(!new_buffer){ return NULL; } alloc = 256; if(buffer){ buffer_content = M_strdup(buffer); M_free(buffer); } va_start(ap, format); length = vsnprintf(new_buffer, alloc, format, ap); if(length == alloc - 1) { /* glibc 2.0 */ do { char *ptr; ptr = M_realloc(new_buffer, alloc + 256); if(!ptr) { length = -1; break; } new_buffer = ptr; alloc += 256; length = vsnprintf(new_buffer, alloc, format, ap); } while(length == alloc - 1); } else if(length >= alloc) { char *ptr; /* glibc 2.x, x > 0 */ ptr = M_realloc(new_buffer, length + 1); if(!ptr) { va_end(ap); return NULL; } new_buffer = ptr; alloc = length + 1; length = vsnprintf(new_buffer, alloc, format, ap); } va_end(ap); if(length<0){ return NULL; } new_buffer[length]='\0'; if(buffer_content){ buffer = m_build_buffer("%s%s", buffer_content, new_buffer); M_free(buffer_content); M_free(new_buffer); }else{ buffer = new_buffer; } return (char * ) buffer; } /* Return a buffer with a new string from string */ char *m_copy_string(const char *string, int pos_init, int pos_end) { unsigned int size, bytes; char *buffer=0; size = (unsigned int) (pos_end - pos_init ) + 1; if(size<=2) size=4; buffer = M_malloc(size); if(!buffer){ return NULL; } if(pos_end>strlen(string) || (pos_init > pos_end)){ return NULL; } bytes = pos_end - pos_init; strncpy(buffer, string+pos_init, bytes); buffer[bytes]='\0'; return (char *) buffer; } /* Rutina para pasar Monkey a daemon */ int set_daemon() { switch (fork()) { case 0 : break; case -1: exit(1); break; /* Error */ default: exit(0); /* Exito */ }; setsid(); /* Crear una nueva sesion */ fclose(stdin); /* Cerrar las salidas en pantallas */ fclose(stderr); fclose(stdout); return 0; } /* Retorna la posicion de search en string */ int str_search(char *string, char *search, int length_cmp) { long int length; long i; if(!string || !search) return -1; length = strlen(string); for(i=0; string[i]!='\0' && i