void Indexer::index_directory(const unicode &dir_path) { /* * Recursively indexes the files in a directory */ for(auto file: kfs::path::list_dir(dir_path.encode())) { auto full_path = kfs::path::join(dir_path.encode(), file); if(kfs::path::is_dir(full_path)) { index_directory(full_path); } else { index_file(full_path); } } }
int get_cachedir_file(request * req, struct stat *statbuf) { char pathname_with_index[MAX_PATH_LENGTH]; int data_fd; time_t real_dir_mtime; real_dir_mtime = statbuf->st_mtime; sprintf(pathname_with_index, "%s/dir.%d.%ld", cachedir, (int) statbuf->st_dev, statbuf->st_ino); data_fd = open(pathname_with_index, O_RDONLY); if (data_fd != -1) { /* index cache */ fstat(data_fd, statbuf); if (statbuf->st_mtime > real_dir_mtime) { statbuf->st_mtime = real_dir_mtime; /* lie */ strcpy(req->request_uri, directory_index); /* for mimetype */ return data_fd; } close(data_fd); unlink(pathname_with_index); /* cache is stale, delete it */ } if (index_directory(req, pathname_with_index) == -1) return -1; data_fd = open(pathname_with_index, O_RDONLY); /* Last chance */ if (data_fd != -1) { strcpy(req->request_uri, directory_index); /* for mimetype */ fstat(data_fd, statbuf); statbuf->st_mtime = real_dir_mtime; /* lie */ return data_fd; } boa_perror(req, "re-opening dircache"); return -1; /* Nothing worked. */ }
int get_cachedir_file(request * req, struct stat *statbuf) { char pathname_with_index[MAX_PATH_LENGTH]; int data_fd; time_t real_dir_mtime; real_dir_mtime = statbuf->st_mtime; sprintf(pathname_with_index, "%s/dir.%d.%ld", cachedir, (int) statbuf->st_dev, statbuf->st_ino); data_fd = open(pathname_with_index, O_RDONLY); if (data_fd != -1) { fstat(data_fd, statbuf); if (statbuf->st_mtime > real_dir_mtime) { statbuf->st_mtime = real_dir_mtime; strcpy(req->request_uri, directory_index); return data_fd; } close(data_fd); unlink(pathname_with_index); } if (index_directory(req, pathname_with_index) == -1) return -1; data_fd = open(pathname_with_index, O_RDONLY); if (data_fd != -1) { strcpy(req->request_uri, directory_index); fstat(data_fd, statbuf); statbuf->st_mtime = real_dir_mtime; return data_fd; } boa_perror(req, "re-opening dircache"); return -1; }
int process_get(request * req) { off_t bytes_written; volatile off_t bytes_to_write; if (req->method == M_HEAD) { return complete_response(req); } bytes_to_write = (req->ranges->stop - req->ranges->start) + 1; if (bytes_to_write > system_bufsize) bytes_to_write = system_bufsize; if (setjmp(env) == 0) { handle_sigbus = 1; bytes_written = write(req->fd, req->data_mem + req->ranges->start, bytes_to_write); handle_sigbus = 0; /* OK, SIGBUS **after** this point is very bad! */ } else { /* sigbus! */ req->status = DEAD; log_error_doc(req); fprintf(stderr, "%sGot SIGBUS in write(2)!\n", get_commonlog_time()); /* sending an error here is inappropriate * if we are here, the file is mmapped, and thus, * a content-length has been sent. If we send fewer bytes * the client knows there has been a problem. * We run the risk of accidentally sending the right number * of bytes (or a few too many) and the client * won't be the wiser. */ return 0; } if (bytes_written < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) return -1; /* request blocked at the pipe level, but keep going */ else { #ifdef QUIET_DISCONNECT if (errno != EPIPE) { #else if (1) { #endif log_error_doc(req); /* Can generate lots of log entries, */ perror("write"); /* OK to disable if your logs get too big */ } req->status = DEAD; return 0; } } req->bytes_written += bytes_written; req->ranges->start += bytes_written; if ((req->ranges->stop + 1 - req->ranges->start) == 0) { return complete_response(req); } return 1; /* more to do */ } /* * Name: get_dir * Description: Called from process_get if the request is a directory. * statbuf must describe directory on input, since we may need its * device, inode, and mtime. * statbuf is updated, since we may need to check mtimes of a cache. * returns: * -1 error * 0 cgi (either gunzip or auto-generated) * >0 file descriptor of file */ int get_dir(request * req, struct stat *statbuf) { char pathname_with_index[MAX_PATH_LENGTH]; int data_fd; if (directory_index) { /* look for index.html first?? */ unsigned int l1, l2; l1 = strlen(req->pathname); l2 = strlen(directory_index); #ifdef GUNZIP if (l1 + l2 + 3 + 1 > sizeof(pathname_with_index)) { /* for .gz */ #else if (l1 + l2 + 1 > sizeof(pathname_with_index)) { #endif errno = ENOMEM; boa_perror(req, "pathname_with_index not large enough for pathname + index"); return -1; } memcpy(pathname_with_index, req->pathname, l1); /* doesn't copy NUL */ memcpy(pathname_with_index + l1, directory_index, l2 + 1); /* does */ data_fd = open(pathname_with_index, O_RDONLY|O_LARGEFILE); if (data_fd != -1) { /* user's index file */ /* We have to assume that directory_index will fit, because * if it doesn't, well, that's a huge configuration problem. * this is only the 'index.html' pathname for mime type */ memcpy(req->request_uri, directory_index, l2 + 1); /* for mimetype */ fstat(data_fd, statbuf); return data_fd; } if (errno == EACCES) { send_r_forbidden(req); return -1; } else if (errno != ENOENT) { /* if there is an error *other* than EACCES or ENOENT */ send_r_not_found(req); return -1; } #ifdef GUNZIP /* if we are here, trying index.html didn't work * try index.html.gz */ strcat(pathname_with_index, ".gz"); data_fd = open(pathname_with_index, O_RDONLY|O_LARGEFILE); if (data_fd != -1) { /* user's index file */ close(data_fd); req->response_status = R_REQUEST_OK; SQUASH_KA(req); if (req->pathname) free(req->pathname); req->pathname = strdup(pathname_with_index); if (!req->pathname) { boa_perror(req, "strdup of pathname_with_index for .gz files " __FILE__ ":" STR(__LINE__)); return 0; } if (req->http_version != HTTP09) { req_write(req, http_ver_string(req->http_version)); req_write(req, " 200 OK-GUNZIP" CRLF); print_http_headers(req); print_last_modified(req); req_write(req, "Content-Type: "); req_write(req, get_mime_type(directory_index)); req_write(req, CRLF CRLF); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } #endif } /* only here if index.html, index.html.gz don't exist */ if (dirmaker != NULL) { /* don't look for index.html... maybe automake? */ req->response_status = R_REQUEST_OK; SQUASH_KA(req); /* the indexer should take care of all headers */ if (req->http_version != HTTP09) { req_write(req, http_ver_string(req->http_version)); req_write(req, " 200 OK" CRLF); print_http_headers(req); print_last_modified(req); req_write(req, "Content-Type: text/html" CRLF CRLF); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); /* in this case, 0 means success */ } else if (cachedir) { return get_cachedir_file(req, statbuf); } else { /* neither index.html nor autogenerate are allowed */ send_r_forbidden(req); return -1; /* nothing worked */ } } static int get_cachedir_file(request * req, struct stat *statbuf) { char pathname_with_index[MAX_PATH_LENGTH]; int data_fd; time_t real_dir_mtime; real_dir_mtime = statbuf->st_mtime; /* the sizeof() doesn't need a -1 because snprintf will * include the NUL when calculating if the size is enough */ snprintf(pathname_with_index, sizeof(pathname_with_index), "%s/dir.%d." PRINTF_OFF_T_ARG, cachedir, (int) statbuf->st_dev, statbuf->st_ino); data_fd = open(pathname_with_index, O_RDONLY|O_LARGEFILE); if (data_fd != -1) { /* index cache */ fstat(data_fd, statbuf); if (statbuf->st_mtime > real_dir_mtime) { statbuf->st_mtime = real_dir_mtime; /* lie */ strcpy(req->request_uri, directory_index); /* for mimetype */ return data_fd; } close(data_fd); unlink(pathname_with_index); /* cache is stale, delete it */ } if (index_directory(req, pathname_with_index) == -1) return -1; data_fd = open(pathname_with_index, O_RDONLY|O_LARGEFILE); /* Last chance */ if (data_fd != -1) { strcpy(req->request_uri, directory_index); /* for mimetype */ fstat(data_fd, statbuf); statbuf->st_mtime = real_dir_mtime; /* lie */ return data_fd; } boa_perror(req, "re-opening dircache"); return -1; /* Nothing worked. */ }
void send_file(per_request *reqInfo, struct stat *fi, char allow_options) { FILE *f; #ifdef BLACKOUT_CODE int isblack = FALSE; #endif /* BLACKOUT_CODE */ if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) { sprintf(error_msg,"%s to non-script",methods[reqInfo->method]); die(reqInfo,SC_NOT_IMPLEMENTED,error_msg); } set_content_type(reqInfo,reqInfo->filename); if((allow_options & OPT_INCLUDES) && (!reqInfo->outh_content_encoding[0])) { #ifdef XBITHACK if((fi->st_mode & S_IXUSR) || (!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE))) { #else if(!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE)) { #endif /* XBITHACK */ reqInfo->bytes_sent = 0; send_parsed_file(reqInfo, allow_options & OPT_INCNOEXEC); log_transaction(reqInfo); return; } } if (reqInfo->path_info[0]) { strcat(reqInfo->filename,reqInfo->path_info); strcat(reqInfo->url,reqInfo->path_info); sprintf(error_msg,"No file matching URL: %s",reqInfo->url); log_reason(reqInfo, error_msg, reqInfo->filename); die(reqInfo,SC_NOT_FOUND,reqInfo->url); } if(!(f=FOpen(reqInfo->filename,"r"))) { if (errno == EACCES) { log_reason(reqInfo,"(1) file permissions deny server access", reqInfo->filename); /* we've already established that it exists */ die(reqInfo,SC_FORBIDDEN,reqInfo->url); } else { /* We know an error occured, of an unexpected variety. * This could be due to no more file descriptors. We have this * child exit after this stage so that errors of state are * swept under the carpet. */ standalone = 0; sprintf(error_msg,"File Open error, errno=%d",errno); log_reason(reqInfo,error_msg,reqInfo->filename); die(reqInfo,SC_SERVER_ERROR,error_msg); } } reqInfo->bytes_sent = 0; #ifdef BLACKOUT_CODE if (!strcmp(reqInfo->outh_content_type,BLACKOUT_MAGIC_TYPE)) { isblack = TRUE; strcpy(reqInfo->outh_content_type,"text/html"); } #endif /* BLACKOUT_CODE */ if(reqInfo->http_version != P_HTTP_0_9) { /* No length dependent headers since black is parsed */ #ifdef BLACKOUT_CODE if (isblack == FALSE) { #endif /* BLACKOUT_CODE */ #ifdef CONTENT_MD5 reqInfo->outh_content_md5 = (unsigned char *)md5digest(f); #endif /* CONTENT_MD5 */ set_content_length(reqInfo,fi->st_size); if (set_last_modified(reqInfo,fi->st_mtime)) { FClose(f); return; } } if (reqInfo->http_version != P_HTTP_0_9) { send_http_header(reqInfo); } #ifdef BLACKOUT_CODE } #endif /* BLACKOUT_CODE */ if(reqInfo->method != M_HEAD) { #ifdef BLACKOUT_CODE if (isblack == TRUE) send_fp_black(reqInfo,f,NULL); else #endif /* BLACKOUT_CODE */ send_fp(reqInfo,f,NULL); } log_transaction(reqInfo); FClose(f); } void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options) { char *name_ptr, *end_ptr; char *ifile, *temp_name; ifile = newString(HUGE_STRING_LEN,STR_TMP); temp_name = newString(HUGE_STRING_LEN,STR_TMP); /* Path Alias (pa) array should now have the trailing slash */ /* if (pa[0] != '/') { */ if ((reqInfo->filename[strlen(reqInfo->filename) - 1] != '/') && (reqInfo->path_info[0] != '/')) { strcpy_dir(ifile,reqInfo->url); construct_url(temp_name,reqInfo->hostInfo,ifile); escape_url(temp_name); die(reqInfo,SC_REDIRECT_PERM,temp_name); } /* Don't allow PATH_INFO to directory indexes as a compromise for error messages for files which don't exist */ if ((reqInfo->path_info[0] != '\0') || (strlen(reqInfo->path_info) > 1)) { strcat(reqInfo->filename,reqInfo->path_info); strcat(reqInfo->url,reqInfo->path_info); sprintf(error_msg,"No file matching URL: %s",reqInfo->url); log_reason(reqInfo, error_msg, reqInfo->filename); freeString(temp_name); freeString(ifile); die(reqInfo,SC_NOT_FOUND,reqInfo->url); } strncpy(temp_name, reqInfo->hostInfo->index_names, HUGE_STRING_LEN-1); end_ptr = name_ptr = temp_name; while (*name_ptr) { while (*name_ptr && isspace (*name_ptr)) ++name_ptr; end_ptr = name_ptr; if (strchr(end_ptr, ' ') ) { end_ptr = strchr(name_ptr, ' '); *end_ptr = '\0'; end_ptr++; } else end_ptr += strlen(end_ptr); make_full_path(reqInfo->filename,name_ptr,ifile); if(stat(ifile,finfo) == -1) { if(! *end_ptr && (allow_options & OPT_INDEXES)) { if (reqInfo->path_info[0]) { strcat(reqInfo->filename,reqInfo->path_info); strcat(reqInfo->url,reqInfo->path_info); log_reason(reqInfo,"file does not exist",reqInfo->filename); freeString(ifile); freeString(temp_name); die(reqInfo,SC_NOT_FOUND,reqInfo->url); } if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) { sprintf(error_msg,"%s to non-script",methods[reqInfo->method]); freeString(ifile); freeString(temp_name); die(reqInfo,SC_NOT_IMPLEMENTED,error_msg); } index_directory(reqInfo); freeString(ifile); freeString(temp_name); return; } else if (! *end_ptr) { log_reason(reqInfo,"(2) file permissions deny server access", reqInfo->filename); freeString(ifile); freeString(temp_name); die(reqInfo,SC_FORBIDDEN,reqInfo->url); } } else { strcpy(reqInfo->filename,ifile); probe_content_type(reqInfo,reqInfo->filename); if(!strcmp(reqInfo->outh_content_type,CGI_MAGIC_TYPE)) send_cgi(reqInfo,finfo,allow_options); else send_file(reqInfo,finfo,allow_options); freeString(ifile); freeString(temp_name); return; } name_ptr = end_ptr; } }