Sean CaronInitial commitd6f64a210 years agoHistory
280 lines · 5.7 KB · C
RawDownload
/* bijou HTTP server for plan 9 by sean caron (scaron@umich.edu) */ #include "main.h" void generate_path(char **path, char **rpath, struct request *req, struct configuration *cfg) { 	char *temp, *head, *tail, *tu; 	int i, j, ft; 	/* check for user directory expansion */ 	if ( req->uri[1] == *(cfg->userchar) ) {					/* work up some temporaries for user directory expansion checks */ 		head = malloc(sizeof(char)*(strlen(req->uri)+1)); 		if ( head == 0 ) {			exits("MALLOC");		} 		tail = malloc(sizeof(char)*(strlen(req->uri)+1)); 		if ( tail == 0 ) {			exits("MALLOC");		} 		tu = malloc(sizeof(char)*(strlen(req->uri)+1)); 		if ( tu == 0 ) {			exits("MALLOC");		} 		strcpy(tu, req->uri); 		temp = strtok(tu, "/"); 		if ( temp == 0 ) {			strcpy(head, "");		} 		else {			strcpy(head, temp);		} 		temp = strtok(0, ""); 		if ( temp == 0 ) { 			/* 			  * strtok obscures whether or not there was a trailing slash followed by nothing else after the			  * first token is chopped in our temporary copy of the URI. we must go back to the original			  * copy of the URI to check for trailing slash. if there was a trailing slash in the URI, reappend			  * it so as to avoid erroneously triggering an HTTP 301 redirect later			*/ 			if ( req->uri[strlen(head)+1] == '/' ) {				strcpy(tail, "/");			} 			/* otherwise set tail to null string. the request will (correctly) trigger HTTP 301 later */ 			else {				strcpy(tail, "");			}		} 		else {			sprintf(tail, "/%s", temp);		} 		/* deal with attempts to get below the user html directory */ 		if ( (strcmp(tail, "/..") == 0) || (strcmp(tail, "/../") == 0) ) { 			*path = malloc( sizeof(char)*(strlen(cfg->rootdir)+2) ); 			if ( *path == 0 ) {				exits("MALLOC");			} 			sprintf(*path, "%s/", cfg->rootdir ); 			req->uri = realloc(req->uri, 2*sizeof(char)); 			if ( req->uri == 0 ) {				exits("REALLOC");			} 			strcpy(req->uri, "/"); 			*rpath = malloc(sizeof(char)*(strlen(cfg->rootdir)+1)); 			if ( *rpath == 0 ) {				exits("MALLOC");			} 			strcpy(*rpath, cfg->rootdir);		} 		/* otherwise construct the translated path as usual */ 		else {			strcpy(head, strtok(head, cfg->userchar)); 			*path = malloc( sizeof(char)*(strlen(cfg->userdir)+strlen(head)+strlen(cfg->userdocs)+strlen(tail)+4) ); 			if ( *path == 0 ) {				exits("MALLOC");			} 			sprintf(*path, "%s/%s/%s%s", cfg->userdir, head, cfg->userdocs, tail); 			*rpath = malloc(sizeof(char)*(strlen(cfg->userdir)+strlen(head)+strlen(cfg->userdocs)+4) ); 			if (*rpath == 0 ) {				exits("MALLOC");			} 			sprintf(*rpath, "%s/%s/%s", cfg->userdir, head, cfg->userdocs);		} 		/* free translation path assembly temporaries */ 		free(tu);		free(head);		free(tail); 	} 	/* path generation, no user directory expansion */ 	else { 		ft = -1; 		/* check directory translations */ 		for ( i = 0; i < cfg->n_translate; i++ ) { 			temp = malloc( sizeof(char)*(strlen(req->uri)+2) ); 			if ( temp == 0 ) {				exits("MALLOC");			} 			/* if uri is at least as long as the translation */ 			if ( strlen(req->uri) >= strlen(*(cfg->translate+(2*i))) ) { 				/* and the first [translation length] characters in the uri are followed immediately by a slash */				/* or there is an exact match between the uri and the translation key in length */ 				if ( (*(req->uri+strlen(*(cfg->translate+(2*i)))) == '/' ) || (strlen(req->uri) == strlen(*(cfg->translate+(2*i)))) ) { 					/* copy that substring to temp */ 					strncpy(temp, req->uri, strlen( *(cfg->translate+(2*i))) );					temp[strlen(*(cfg->translate+(2*i)))] = '\0'; 					/* and if there is an exact match between temp and the translation */ 					if ( strcmp(temp, *(cfg->translate+(2*i)) ) == 0 ) { 						/* then we found a match; flag it and break out of the loop */ 						ft = i;						free(temp);						break;					}				}			} 			free(temp);		} 		/* translation, no user directory expansion */ 		if ( ft != -1 ) { 			temp = malloc( sizeof(char)*(strlen(req->uri)+2) ); 			if ( temp == 0 ) {				exits("MALLOC");			} 			j = 0; 			for ( i = strlen(*(cfg->translate+(2*ft))); i < strlen(req->uri); i++) { 				*(temp+j) = *(req->uri+i);				j++; 			} 			*(temp+j) = '\0'; 			/* deal with attempts to get below the translated root */ 			if ( (strcmp(temp, "/..") == 0) || (strcmp(temp, "/../") == 0) ) {				*path = malloc( sizeof(char)*(strlen(cfg->rootdir)+2) ); 				if ( *path == 0 ) {					exits("MALLOC");				} 				sprintf(*path, "%s/", cfg->rootdir ); 				req->uri = realloc(req->uri, 2*sizeof(char)); 				if ( req->uri == 0 ) {					exits("REALLOC");				} 				strcpy(req->uri, "/"); 				*rpath = malloc( sizeof(char)*(strlen(cfg->rootdir)+1) ); 				if ( *rpath == 0 ) {					exits("MALLOC");				} 				strcpy(*rpath, cfg->rootdir);			} 			/* otherwise apply translation as usual */ 			else { 				*path = malloc( (strlen(*(cfg->translate+((2*ft)+1)))+strlen(temp)+2)*sizeof(char) ); 				if ( *path == 0 ) {					exits("MALLOC");				} 				sprintf(*path, "%s%s", *(cfg->translate+((2*ft)+1)), temp ); 				*rpath = malloc( sizeof(char)*(strlen(*(cfg->translate+((2*ft)+1)))+2) ); 				if ( *rpath == 0 ) {					exits("MALLOC");				} 				strcpy(*rpath, *(cfg->translate+((2*ft)+1)) );			} 			free(temp); 		} 		/* no user directory expansion, no translation */ 		else { 			/* allocate some memory for the real file path */ 			*path = malloc((strlen(cfg->rootdir)+strlen(req->uri)+1)*sizeof(char)); 			if ( path == 0 ) {				exits("MALLOC");			} 			/* catenate the http server directory root with the uri to get a real file path */ 			sprintf(*path, "%s%s", cfg->rootdir, req->uri ); 			*rpath = malloc(sizeof(char)*(strlen(cfg->rootdir)+2) ); 			if ( *rpath == 0 ) {				exits("MALLOC");			} 			strcpy(*rpath, cfg->rootdir); 		}	} 	return;}