int tt(HTTPCONNECTION hc, void *p) { static i=0; request *req = (request *)hc; printf("--->[%s]\n[%s]\n", req->pathname, req->query_string); //printf("-------------------->oks\n"); if (GetHttpMethod(hc) == M_GET) { FILE *fp; struct stat st; int success = 0; char *pcF[] = {"/CamImg1542.jpg", "/CamImg2328.jpg"} ; char *pcFile; i++; i %= 2; pcFile = GetDocumentBasedPath(pcF[i]); if (pcFile) { if (stat(pcFile, &st) == 0) { fp = fopen(pcFile, "rb"); if (fp) { char *pc; pc = malloc(st.st_size); fread(pc, st.st_size, 1, fp); AddHttpBody(hc, pc, st.st_size); SetHttpHeader(hc, 200, "OK", NULL, "Expires: 01 Jan 1970 00:00:00 GMT\r\nCache-Control: no-cache\r\n", "image/jpeg", TRUE); free(pc); fclose(fp); success = 1; } } free(pcFile); } if (!success) send_r_not_found(hc); return 0; } else // SetPostDataFun(hc, t1, p); return -1; }
int init_get(request * req) { int data_fd, saved_errno; struct stat statbuf; volatile off_t bytes_free; data_fd = open(req->pathname, O_RDONLY|O_LARGEFILE); saved_errno = errno; /* might not get used */ while (use_lang_rewrite && data_fd == -1 && errno == ENOENT) { /* We cannot open that file - Check whether we can rewrite it * to a different language suffix. We only support filenames * of the format: "foo.ll.html" as an alias for "foo.html". */ unsigned int len; len = strlen(req->pathname); if (len < 6 || strcmp (req->pathname + len - 5, ".html")) break; /* does not end in ".html" */ if (len > 8 && req->pathname[len-8] == '.' && req->pathname[len-7] >= 'a' && req->pathname[len-7] <= 'z' && req->pathname[len-6] >= 'a' && req->pathname[len-6] <= 'z') { /* The request was for a language dependent file. Strip * it and try the generic form. */ char save_name[8]; strcpy (save_name, req->pathname + len - 7); strcpy (req->pathname + len - 7, "html"); data_fd = open(req->pathname, O_RDONLY); if (data_fd == -1) strcpy (req->pathname + len - 7, save_name); break; } else if ( 0 ) { /* Fixme: Other items to try from the list of accepted_languages */ data_fd = open(req->pathname, O_RDONLY); } else break; } #ifdef GUNZIP if (data_fd == -1 && errno == ENOENT) { /* cannot open */ /* it's either a gunzipped file or a directory */ char gzip_pathname[MAX_PATH_LENGTH]; unsigned int len; len = strlen(req->pathname); if (len + 4 > sizeof(gzip_pathname)) { log_error_doc(req); fprintf(stderr, "Pathname + .gz too long! (%s)\n", req->pathname); send_r_bad_request(req); return 0; } memcpy(gzip_pathname, req->pathname, len); memcpy(gzip_pathname + len, ".gz", 3); gzip_pathname[len + 3] = '\0'; data_fd = open(gzip_pathname, O_RDONLY|O_LARGEFILE); if (data_fd != -1) { close(data_fd); req->response_status = R_REQUEST_OK; if (req->pathname) free(req->pathname); req->pathname = strdup(gzip_pathname); if (!req->pathname) { boa_perror(req, "strdup req->pathname for gzipped filename " __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_content_type(req); print_last_modified(req); req_write(req, CRLF); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } } #endif if (data_fd == -1) { log_error_doc(req); errno = saved_errno; perror("document open"); if (saved_errno == ENOENT) send_r_not_found(req); else if (saved_errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; } #ifdef ACCESS_CONTROL if (!access_allow(req->pathname)) { send_r_forbidden(req); return 0; } #endif fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { /* directory */ close(data_fd); /* close dir */ if (req->pathname[strlen(req->pathname) - 1] != '/') { char buffer[3 * MAX_PATH_LENGTH + 128]; unsigned int len; #ifdef ALLOW_LOCAL_REDIRECT len = strlen(req->request_uri); if (len + 2 > sizeof(buffer)) { send_r_error(req); return 0; } memcpy(buffer, req->request_uri, len); buffer[len] = '/'; buffer[len+1] = '\0'; #else char *host = server_name; unsigned int l2; char *port = NULL; const char *prefix = hsts_header? "https://" : "http://"; static unsigned int l3 = 0; static unsigned int l4 = 0; if (l4 == 0) { l4 = strlen(prefix); } len = strlen(req->request_uri); if (!port && server_port != 80 && !no_redirect_port) { port = strdup(simple_itoa(server_port)); if (port == NULL) { errno = ENOMEM; boa_perror(req, "Unable to perform simple_itoa conversion on server port!"); return 0; } l3 = strlen(port); } /* l3 and l4 are done */ if (req->host) { /* only shows up in vhost mode */ /* what about the port? (in vhost_mode?) */ /* we don't currently report ports that differ * from out "bound" (listening) port, so we don't care */ host = req->host; } l2 = strlen(host); if (server_port != 80 && !no_redirect_port) { if (l4 + l2 + 1 + l3 + len + 1 > sizeof(buffer)) { errno = ENOMEM; boa_perror(req, "buffer not large enough for directory redirect"); return 0; } memcpy(buffer, prefix, l4); memcpy(buffer + l4, host, l2); buffer[l4 + l2] = ':'; memcpy(buffer + l4 + l2 + 1, port, l3); memcpy(buffer + l4 + l2 + 1 + l3, req->request_uri, len); buffer[l4 + l2 + 1 + l3 + len] = '/'; buffer[l4 + l2 + 1 + l3 + len + 1] = '\0'; } else { if (l4 + l2 + len + 1 > sizeof(buffer)) { errno = ENOMEM; boa_perror(req, "buffer not large enough for directory redirect"); return 0; } memcpy(buffer, prefix, l4); memcpy(buffer + l4, host, l2); memcpy(buffer + l4 + l2, req->request_uri, len); buffer[l4 + l2 + len] = '/'; buffer[l4 + l2 + len + 1] = '\0'; } #endif /* ALLOW LOCAL REDIRECT */ send_r_moved_perm(req, buffer); return 0; } data_fd = get_dir(req, &statbuf); /* updates statbuf */ if (data_fd < 0) /* couldn't do it */ return 0; /* errors reported by get_dir */ else if (data_fd == 0 || data_fd == 1) return data_fd; /* else, data_fd contains the fd of the file... */ } if (!S_ISREG(statbuf.st_mode)) { /* regular file */ log_error_doc(req); fprintf(stderr, "Resulting file is not a regular file.\n"); send_r_bad_request(req); close(data_fd); return 0; } /* If-UnModified-Since asks * is the file newer than date located in time_cval * yes -> return 412 * no -> return 200 * * If-Modified-Since asks * is the file date less than or same as the date located in time_cval * yes -> return 304 * no -> return 200 * * If-Unmodified-Since overrides If-Modified-Since */ /* if (req->headers[H_IF_UNMODIFIED_SINCE] && modified_since(&(statbuf.st_mtime), req->headers[H_IF_UNMODIFIED_SINCE])) { send_r_precondition_failed(req); return 0; } else */ if (req->if_modified_since && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } req->filesize = statbuf.st_size; req->last_modified = statbuf.st_mtime; /* ignore if-range without range */ if (req->header_ifrange && !req->ranges) req->header_ifrange = NULL; /* we don't support it yet */ req->header_ifrange = NULL; /* parse ranges now */ /* we have to wait until req->filesize exists to fix them up */ /* fixup handles handles communicating with the client */ /* ranges_fixup logs as appropriate, and sends * send_r_invalid_range on error. */ if (req->filesize == 0) { if (req->http_version < HTTP11) { send_r_request_ok(req); close(data_fd); return 0; } send_r_no_content(req); close(data_fd); return 0; } if (req->ranges && !ranges_fixup(req)) { close(data_fd); return 0; } /* if no range has been set, use default range */ #if 0 DEBUG(DEBUG_RANGE) { log_error_time(); fprintf(stderr, "if-range: %s\time_cval: %d\tmtime: %d\n", req->header_ifrange, req->time_cval, statbuf->st_mtime); } #endif /* If the entity tag given in the If-Range header matches the current entity tag for the entity, then the server should provide the specified sub-range of the entity using a 206 (Partial content) response. If the entity tag does not match, then the server should return the entire entity using a 200 (OK) response. */ /* IF we have range data *and* no if-range or if-range matches... */ #ifdef MAX_FILE_MMAP if (req->filesize > MAX_FILE_MMAP) { req->data_fd = data_fd; req->status = IOSHUFFLE; } else #endif { /* NOTE: I (Jon Nelson) tried performing a read(2) * into the output buffer provided the file data would * fit, before mmapping, and if successful, writing that * and stopping there -- all to avoid the cost * of a mmap. Oddly, it was *slower* in benchmarks. */ req->mmap_entry_var = find_mmap(data_fd, &statbuf); if (req->mmap_entry_var == NULL) { req->data_fd = data_fd; req->status = IOSHUFFLE; } else { req->data_mem = req->mmap_entry_var->mmap; close(data_fd); /* close data file */ } } if (!req->ranges) { req->ranges = range_pool_pop(); req->ranges->start = 0; req->ranges->stop = -1; if (!ranges_fixup(req)) { return 0; } send_r_request_ok(req); } else { /* FIXME: support if-range header here, by the following logic: * if !req->header_ifrange || st_mtime > header_ifrange, * send_r_partial_content * else * reset-ranges, etc... */ if (!req->header_ifrange) { send_r_partial_content(req); } else { /* either no if-range or the if-range does not match */ ranges_reset(req); req->ranges = range_pool_pop(); req->ranges->start = 0; req->ranges->stop = -1; if (!ranges_fixup(req)) { return 0; } send_r_request_ok(req); } } if (req->method == M_HEAD) { return complete_response(req); } bytes_free = 0; if (req->data_mem) { /* things can really go tilt if req->buffer_end > BUFFER_SIZE, * but basically that can't happen */ /* We lose statbuf here, so make sure response has been sent */ bytes_free = BUFFER_SIZE - req->buffer_end; /* 256 bytes for the **trailing** headers */ /* bytes is now how much the buffer can hold * after the headers */ } if (req->data_mem && bytes_free > 256) { unsigned int want; Range *r; r = req->ranges; want = (r->stop - r->start) + 1; if (bytes_free > want) bytes_free = want; else { /* bytes_free <= want */ ; } if (setjmp(env) == 0) { handle_sigbus = 1; memcpy(req->buffer + req->buffer_end, req->data_mem + r->start, bytes_free); handle_sigbus = 0; /* OK, SIGBUS **after** this point is very bad! */ } else { /* sigbus! */ log_error_doc(req); reset_output_buffer(req); send_r_error(req); log_error("Got SIGBUS in memcpy\n"); return 0; } req->buffer_end += bytes_free; req->bytes_written += bytes_free; r->start += bytes_free; if (bytes_free == want) { /* this will fit due to the 256 extra bytes_free */ return complete_response(req); } } /* We lose statbuf here, so make sure response has been sent */ 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 handleForm(request *req) { char *ptr; int i; #define SCRIPT_ALIAS "/boafrm/" //fprintf(stderr, "###%s:%d req->request_uri=%s###\n", __FILE__, __LINE__, req->request_uri); #ifdef ACTIONTEC_WCB int cgi_flag = 1; ptr = strstr(req->request_uri, ".cgi"); if(!ptr) { ptr = strstr(req->request_uri, SCRIPT_ALIAS); cgi_flag = 0; } #else ptr = strstr(req->request_uri, SCRIPT_ALIAS); #endif apmib_get(MIB_WAN_DHCP, (void *)&last_wantype); if (ptr==NULL) { send_r_not_found(req); return; } else { form_name_t *now_form; #ifdef ACTIONTEC_WCB if(cgi_flag) ptr = '\0'; else ptr += strlen(SCRIPT_ALIAS); #else ptr+=strlen(SCRIPT_ALIAS); #endif for (i=0; root_form[i].name!=NULL; i++) { now_form = &root_form[i]; #ifdef ACTIONTEC_WCB if((cgi_flag && strstr(req->request_uri, now_form->name)) || (!cgi_flag && (strlen(ptr) == strlen(now_form->name)) && (memcmp(ptr,now_form->name,strlen(now_form->name))==0))) { #else if ((strlen(ptr) == strlen(now_form->name)) && (memcmp(ptr,now_form->name,strlen(now_form->name))==0)) { #endif send_r_request_ok2(req); /* All's well */ /*#ifdef USE_AUTH if (req->auth_flag == 1) { // user //brad add for wizard if(!strcmp(req->request_uri,"/boafrm/formSetEnableWizard")){ send_redirect_perm(req, "/wizard_back.htm"); }else{ //ptr= (char *)req_get_cstream_var(req, ("webpage"), ("")); //strcpy(last_url, ptr); //sprintf(ok_msg,"%s","\"Only <b>admin</b> account can change the settings.<br>\""); //send_redirect_perm(req, WEB_PAGE_APPLY_OK); ptr= (char *)req_get_cstream_var(req, ("webpage"), ("")); if(ptr ==NULL) sprintf(last_url, "/%s", directory_index); else strcpy(last_url, ptr); if(!strcmp(req->request_uri,"/boafrm/formSetRestorePrev") || !strcmp(req->request_uri,"/boafrm/formSetFactory")){ sprintf(last_url, "%s","util_savesetting.asp"); if (req->upload_data) free(req->upload_data); } if(!strcmp(req->request_uri,"/boafrm/formFirmwareUpgrade")){ sprintf(last_url, "%s","util_firmware.asp"); if (req->upload_data) free(req->upload_data); } if(!strcmp(req->request_uri,"/boafrm/formWPS")){ wps_action= (char *)req_get_cstream_var(req, ("wpsAction"), ("")); if(!strcmp(wps_action, "pbc") || !strcmp(wps_action, "pin")){ now_form->function(req,NULL,NULL); freeAllTempStr(); return; } } sprintf(ok_msg,"%s","\"Only <b>admin</b> account can change the settings.<br>\""); send_redirect_perm(req, WEB_PAGE_APPLY_OK); } } else #endif*/ now_form->function(req,NULL,NULL); update_content_length(req); freeAllTempStr(); return; } } } send_r_not_found(req); } void handleScript(request *req,char *left1,char *right1) { char *left=left1,*right=right1; asp_name_t *now_asp; unsigned int funcNameLength; int i, j; left += 2; right -= 1; while (1) { while (*left==' ') {if(left>=right) break;++left;} while (*left==';') {if(left>=right) break;++left;} while (*left=='(') {if(left>=right) break;++left;} while (*left==')') {if(left>=right) break;++left;} while (*left==',') {if(left>=right) break;++left;} if (left >= right) break; /* count the function name length */ { char *ptr = left; funcNameLength = 0; while (*ptr!='(' && *ptr!=' ') { ptr++; funcNameLength++; if ((unsigned int )ptr >= (unsigned int)right) { break; } } } for (j=0; root_asp[j].name!=NULL; j++) { now_asp = &root_asp[j]; if ((strlen(now_asp->name) == funcNameLength) && (memcmp(left,now_asp->name,strlen(now_asp->name))==0)) { char *leftc,*rightc; int argc=0; char *argv[8]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; left += strlen(now_asp->name); while (1) { int size,exit=0; while (1) { if (*left==')') { exit=1; break; } if (*left=='\"') break; if ((unsigned int)left > (unsigned int)right) { exit=1; break; } left++; } if (exit==1) break; leftc = left; leftc++; rightc = strstr(leftc,"\""); if (rightc==NULL) break; size = (unsigned int)rightc-(unsigned int)leftc+1; argv[argc] = (char *)malloc(size); if (argv[argc]==NULL) break; memcpy(argv[argc],leftc,size-1); argv[argc][size-1] = '\0'; argc++; left = rightc + 1; } //fprintf(stderr, "###%s:%d now_asp->name=%s###\n", __FILE__, __LINE__, now_asp->name); now_asp->function(req,argc,argv); for (i=0; i<argc; i++) free(argv[i]); break; } } ++left;
int init_get(request * req) { int data_fd, saved_errno; struct stat statbuf; volatile unsigned int bytes_free; //fprintf(stderr, "###[%s %d] req->pathname=%s###\n", __FUNCTION__, __LINE__, req->pathname); //fprintf(stderr, "###[%s %d] req->client_stream=%s###\n", __FUNCTION__, __LINE__, req->client_stream); //fprintf(stderr, "###[%s %d] req->logline=%s###\n", __FUNCTION__, __LINE__, req->logline); //fprintf(stderr, "###[%s %d] req->request_uri=%s###\n", __FUNCTION__, __LINE__, req->request_uri); //fprintf(stderr, "###[%s %d] req->host=%s###\n", __FUNCTION__, __LINE__, req->host); /* A special GET request: "GET /boaform/formWlanRedirect?redirect-url=wlbasic.htm&wlan_id=0 HTTP/1.1" */ if (strstr(req->request_uri, "formWlanRedirect")) { char *redirectUrl, *strWlanId, *ptr; extern void formWlanRedirect2(request *wp, char *redirectUrl, char *strWlanId); if ((ptr = strstr(req->client_stream, "redirect-url="))) { redirectUrl = ptr + strlen("redirect-url="); if ((ptr = strstr(redirectUrl, "&wlan_id="))) { *ptr = '\0'; strWlanId = ptr + strlen("&wlan_id="); if ((ptr = strstr(strWlanId, " HTTP"))) { *ptr = '\0'; //fprintf(stderr, "###[%s %d] redirectUrl=%s strWlanId=%s###\n", __FUNCTION__, __LINE__, redirectUrl, strWlanId); formWlanRedirect2(req, redirectUrl, strWlanId); return 0; } } } } data_fd = open(req->pathname, O_RDONLY); saved_errno = errno; /* might not get used */ #ifdef GUNZIP if (data_fd == -1 && errno == ENOENT) { /* cannot open */ /* it's either a gunzipped file or a directory */ char gzip_pathname[MAX_PATH_LENGTH]; unsigned int len; len = strlen(req->pathname); if (len + 4 > sizeof(gzip_pathname)) { log_error_doc(req); fprintf(stderr, "Pathname + .gz too long! (%s)\n", req->pathname); send_r_bad_request(req); return 0; } memcpy(gzip_pathname, req->pathname, len); memcpy(gzip_pathname + len, ".gz", 3); gzip_pathname[len + 3] = '\0'; data_fd = open(gzip_pathname, O_RDONLY); if (data_fd != -1) { close(data_fd); req->response_status = R_REQUEST_OK; if (req->pathname) free(req->pathname); req->pathname = strdup(gzip_pathname); if (!req->pathname) { boa_perror(req, "strdup req->pathname for gzipped filename " __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_content_type(req); print_last_modified(req); req_write(req, CRLF); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } } #endif if (data_fd == -1) { log_error_doc(req); errno = saved_errno; DEBUG(DEBUG_BOA) { perror("document open"); fprintf(stderr, "req->pathname=%s\n", (req->pathname ? req->pathname : "null")); } #if 0 if (saved_errno == ENOENT) send_r_not_found(req); else if (saved_errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); #else send_redirect_perm(req,"home.htm"); #endif return 0; }
int init_get2(request * req) { int data_fd; //Brad add begin for update content length char *content_length_orig1; char *content_length_orig2; int orig_char_length=0; int exact_char_length=0; int byte_shift=0; int exact_size=0; int total_length_shift=0; char *exact_content=NULL; int head_offset=0; int first_offset=0; int antecedent_segment=0; int subsequent_segment=0; //Brad add end for update content length #ifdef GUNZIP char buf[MAX_PATH_LENGTH]; #endif struct stat statbuf; SQUASH_KA(req); complete_env(req); middle_segment=0; req->cgi_env[req->cgi_env_index] = NULL; /* terminate cgi env */ if ((strstr(req->request_uri,".htm")==NULL) && (strstr(req->request_uri,".asp")==NULL)) { return 1; } data_fd = open(req->pathname, O_RDONLY); if (data_fd == -1) { /* cannot open */ #ifdef GUNZIP sprintf(buf, "%s.gz", req->pathname); data_fd = open(buf, O_RDONLY); if (data_fd == -1) { #endif int errno_save = errno; log_error_doc(req); errno = errno_save; #if 0 perror("document open"); #endif // syslog(LOG_ERR, "Error opening %s for %s: %s\n", req->pathname, // req->remote_ip_addr, strerror(errno_save)); errno = errno_save; if (errno == ENOENT) send_r_not_found(req); else if (errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; #ifdef GUNZIP } close(data_fd); req->response_status = R_REQUEST_OK; if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_content_type(req); print_last_modified(req); req_write(req, "\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; if (req->pathname) free(req->pathname); req->pathname = strdup(buf); return init_cgi(req); /* 1 - OK, 2 - die */ #endif } fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { close(data_fd); /* close dir */ if (req->pathname[strlen(req->pathname) - 1] != '/') { char buffer[3 * MAX_PATH_LENGTH + 128]; if (server_port != 80) sprintf(buffer, "http://%s:%d%s/", req->host?req->host:server_name, server_port, req->request_uri); else sprintf(buffer, "http://%s%s/", req->host?req->host:server_name, req->request_uri); send_redirect_perm(req, buffer); return 0; } data_fd = get_dir(req, &statbuf); /* updates statbuf */ if (data_fd == -1) { /* couldn't do it */ return 0; /* errors reported by get_dir */ } else if (data_fd == 0) { return 1; } } //start modify here : tony #if 0 if (req->if_modified_since && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } #endif req->filesize = statbuf.st_size; // req->last_modified = statbuf.st_mtime; if (req->method == M_HEAD) { send_r_request_ok(req); close(data_fd); return 0; } /* MAP_OPTIONS: see compat.h */ req->data_mem = mmap(0, req->filesize, #ifdef USE_NLS PROT_READ|PROT_WRITE #else PROT_READ #endif , MAP_OPTIONS,data_fd, 0); close(data_fd); /* close data file */ if ((long) req->data_mem == -1) { boa_perror(req, "mmap"); return 0; } send_r_request_ok(req); /* All's well */ { //parse and send asp page char *left,*right,*last_right=req->data_mem; int bob; first_offset=req->buffer_end; //Brad add for update content length while (1) { left=strstr(last_right,"<%"); if (left!=NULL) right=strstr(left,"%>"); if ((left!=NULL) && (right!=NULL)) { bob=(unsigned int)left-(unsigned int)last_right; #ifdef SUPPORT_ASP while((bob+req->buffer_end+10)>(req->max_buffer_size)) { //Brad modify int ret; ret=allocNewBuffer(req); if (ret==-1) { bob=req->max_buffer_size- req->buffer_end; printf("will break\n"); break; } } #endif antecedent_segment =antecedent_segment+bob; //Brad add for update content length if (bob>=0) { memcpy(req->buffer + req->buffer_end, req->data_mem + req->filepos, bob); last_right=right+2; req->buffer_end += bob; req->filepos += (bob+(unsigned int)last_right-(unsigned int)left); handleScript(req,left,right); } } else { bob=(unsigned int)req->data_mem+req->filesize-(unsigned int)last_right; #ifdef SUPPORT_ASP while((bob+req->buffer_end+10)>req->max_buffer_size) { //Brad modify int ret; ret=allocNewBuffer(req); if (ret==-1) { bob=req->max_buffer_size- req->buffer_end; break; } } #endif subsequent_segment = subsequent_segment+bob; //Brad add for update content length if (bob > 0) { memcpy(req->buffer + req->buffer_end, req->data_mem + req->filepos, bob); req->buffer_end += bob; req->filepos += bob; } break; } } } //Brad add begin for update content length exact_content = req->buffer+first_offset; exact_size = antecedent_segment+middle_segment+subsequent_segment; //fprintf(stderr, "the exact total length of asp file=%d\n", exact_size); content_length_orig1 = strstr(req->buffer, "Content-Length:"); content_length_orig2 = strstr(content_length_orig1, "\r\n"); content_length_orig1 = content_length_orig1 + strlen("Content-Length: "); orig_char_length = content_length_orig2 - content_length_orig1; //fprintf(stderr, "the orig_char_length=%d\n", orig_char_length); exact_char_length = strlen(simple_itoa(exact_size)); //fprintf(stderr, "the exact_char_length=%d\n", exact_char_length); if(orig_char_length == exact_char_length) { //fprintf(stderr, "Update the content length with the same char length!\n"); memcpy(content_length_orig1, simple_itoa(exact_size),exact_char_length); }else if(orig_char_length < exact_char_length) { //fprintf(stderr, " Update the content length with shift to later bytes!\n"); byte_shift = exact_char_length - orig_char_length; head_offset = first_offset- (content_length_orig2 - req->buffer); total_length_shift = head_offset+exact_size; memmove((content_length_orig2+byte_shift), content_length_orig2, total_length_shift); memcpy(content_length_orig1, simple_itoa(exact_size),exact_char_length); req->buffer_end = req->buffer_end+byte_shift; }else { //fprintf(stderr, "Update the content length with shift to preceding bytes!\n"); byte_shift = orig_char_length - exact_char_length; head_offset = first_offset- (content_length_orig2 - req->buffer); total_length_shift = head_offset+exact_size; memmove((content_length_orig2-byte_shift), content_length_orig2, total_length_shift); memcpy(content_length_orig1, simple_itoa(exact_size),exact_char_length); req->buffer_end = req->buffer_end-byte_shift; } //Brad add end for update content length if (req->filepos == req->filesize) { // req->status = CLOSE; return 0; /* done! */ } /* We lose statbuf here, so make sure response has been sent */ return 1; }
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?? */ strcpy(pathname_with_index, req->pathname); strcat(pathname_with_index, directory_index); /* sprintf(pathname_with_index, "%s%s", req->pathname, directory_index); */ data_fd = open(pathname_with_index, O_RDONLY); if (data_fd != -1) { /* user's index file */ strcpy(req->request_uri, directory_index); /* 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); 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) { log_error_time(); perror("strdup"); send_r_error(req); return 0; } if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_last_modified(req); req_write(req, "Content-Type: "); req_write(req, get_mime_type(directory_index)); req_write(req, "\r\n\r\n"); 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->simple) { req_write(req, "HTTP/1.0 200 OK\r\n"); print_http_headers(req); print_last_modified(req); req_write(req, "Content-Type: text/html\r\n\r\n"); 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 */ } }
int init_get(request * req) { int data_fd, saved_errno, dynamic=0; struct stat statbuf; volatile int bytes; data_fd = open(req->pathname, O_RDONLY); saved_errno = errno; /* might not get used */ #ifdef GUNZIP if (data_fd == -1 && errno == ENOENT) { /* cannot open */ /* it's either a gunzipped file or a directory */ char gzip_pathname[MAX_PATH_LENGTH]; int len; len = strlen(req->pathname); memcpy(gzip_pathname, req->pathname, len); memcpy(gzip_pathname + len, ".gz", 3); gzip_pathname[len + 3] = '\0'; data_fd = open(gzip_pathname, O_RDONLY); if (data_fd != -1) { close(data_fd); req->response_status = R_REQUEST_OK; if (req->pathname) free(req->pathname); req->pathname = strdup(gzip_pathname); if (!req->pathname) { log_error_time(); perror("strdup"); send_r_error(req); return 0; } if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_content_type(req); print_last_modified(req); req_write(req, "\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } } #endif if (data_fd == -1) { log_error_doc(req); errno = saved_errno; perror("document open"); if (saved_errno == ENOENT) send_r_not_found(req); else if (saved_errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; } fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { /* directory */ close(data_fd); /* close dir */ if (req->pathname[strlen(req->pathname) - 1] != '/') { char buffer[3 * MAX_PATH_LENGTH + 128]; if (server_port != 80) sprintf(buffer, "http://%s:%d%s/", server_name, server_port, req->request_uri); else sprintf(buffer, "http://%s%s/", server_name, req->request_uri); send_r_moved_perm(req, buffer); return 0; } data_fd = get_dir(req, &statbuf); /* updates statbuf */ if (data_fd == -1) /* couldn't do it */ return 0; /* errors reported by get_dir */ else if (data_fd <= 1) /* data_fd == 0 -> close it down, 1 -> continue */ return data_fd; /* else, data_fd contains the fd of the file... */ } #ifdef DAVINCI_IPCAM if (req->http_uri && (req->http_uri->uri_flag & URI_FLAG_NEED_PARSE)) dynamic = 1; #endif if (req->if_modified_since && !dynamic && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } req->filesize = statbuf.st_size; req->last_modified = statbuf.st_mtime; if (req->method == M_HEAD || req->filesize == 0) { send_r_request_ok(req); close(data_fd); return 0; } if (req->filesize > MAX_FILE_MMAP) { send_r_request_ok(req); /* All's well */ req->status = PIPE_READ; req->cgi_status = CGI_BUFFER; req->data_fd = data_fd; req_flush(req); /* this should *always* complete due to the size of the I/O buffers */ req->header_line = req->header_end = req->buffer; return 1; } if (req->filesize == 0) { /* done */ send_r_request_ok(req); /* All's well *so far* */ close(data_fd); return 1; } /* NOTE: I (Jon Nelson) tried performing a read(2) * into the output buffer provided the file data would * fit, before mmapping, and if successful, writing that * and stopping there -- all to avoid the cost * of a mmap. Oddly, it was *slower* in benchmarks. */ req->mmap_entry_var = find_mmap(data_fd, &statbuf); if (req->mmap_entry_var == NULL) { req->buffer_end = 0; if (errno == ENOENT) send_r_not_found(req); else if (errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); close(data_fd); return 0; } req->data_mem = req->mmap_entry_var->mmap; close(data_fd); /* close data file */ if ((long) req->data_mem == -1) { boa_perror(req, "mmap"); return 0; } #ifdef DAVINCI_IPCAM if (dynamic) { char *addr = (char *)malloc(req->filesize + 1025); if (addr) { req->mem_flag |= MFLAG_IS_MEMORY; req->mmap_ptr = req->data_mem; req->mmap_size = req->filesize; memcpy(addr+1024, req->data_mem, req->filesize); addr[req->filesize+1024] = '\0'; req->data_mem = addr; req->filesize = html_argument_parse(req->authority, addr+1024, req->data_mem); send_request_ok_no_cache(req); /* All's well */ return 1; } } #endif // DAVINCI_IPCAM send_r_request_ok(req); /* All's well */ bytes = BUFFER_SIZE - req->buffer_end; /* bytes is now how much the buffer can hold * after the headers */ if (bytes > 0) { if (bytes > req->filesize) bytes = req->filesize; if (sigsetjmp(env, 1) == 0) { handle_sigbus = 1; memcpy(req->buffer + req->buffer_end, req->data_mem, bytes); handle_sigbus = 0; /* OK, SIGBUS **after** this point is very bad! */ } else { /* sigbus! */ log_error_doc(req); reset_output_buffer(req); send_r_error(req); fprintf(stderr, "%sGot SIGBUS in memcpy!\n", get_commonlog_time()); return 0; } req->buffer_end += bytes; req->filepos += bytes; if (req->filesize == req->filepos) { req_flush(req); req->status = DONE; } } /* We lose statbuf here, so make sure response has been sent */ return 1; }
int init_get(request * req) { int data_fd; char buf[MAX_PATH_LENGTH]; struct stat statbuf; data_fd = open(req->pathname, O_RDONLY, 0); if (data_fd == -1) { /* cannot open */ int errno_save = errno; errno = errno_save; #if 0 perror("document open"); #endif printf("%s", req->pathname);PTI; my_syslog(LOG_ERR, "Error opening %s, %s\n", req->pathname, strerror(errno_save)); errno = errno_save; if (errno == ENOENT) send_r_not_found(req); else if (errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; } fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { /* directory */ close(data_fd); /* close dir */ data_fd = get_dir(req, &statbuf); /* updates statbuf */ if (data_fd == -1) /* couldn't do it */ return 0; /* errors reported by get_dir */ else if (data_fd == 0) return 1; } if (req->if_modified_since && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } req->filesize = statbuf.st_size; req->last_modified = statbuf.st_mtime; if (req->method == M_HEAD) { send_r_request_ok(req); close(data_fd); return 0; } req->data_mem_length = req->filesize; req->data_mem = (char *)malloc(req->filesize); if (req->data_mem) { if (read(data_fd, req->data_mem, req->filesize) != req->filesize) { free(req->data_mem); req->data_mem = NULL; } } close(data_fd); if (req->data_mem == NULL) { boa_perror(req, "mmap"); return 0; } send_r_request_ok(req); /* All's well */ { int bob; bob = BUFFER_SIZE - req->buffer_end; if (bob > 0) { if (bob > req->filesize - req->filepos) bob = req->filesize - req->filepos; memcpy(req->buffer + req->buffer_end, req->data_mem + req->filepos, bob); req->buffer_end += bob; req->filepos += bob; } } if (req->filepos == req->filesize) { req->status = CLOSE; return 0; /* done! */ } /* We lose statbuf here, so make sure response has been sent */ return 1; }
int init_get(request * req) { int data_fd; char buf[MAX_PATH_LENGTH]; struct stat statbuf; req->cgi_env[req->cgi_env_index] = NULL; /* terminate cgi env */ data_fd = open(req->pathname, O_RDONLY); if (data_fd == -1) { /* cannot open */ #ifdef GUNZIP sprintf(buf, "%s.gz", req->pathname); data_fd = open(buf, O_RDONLY); if (data_fd == -1) { #endif int errno_save = errno; log_error_doc(req); errno = errno_save; #if 0 perror("document open"); #endif syslog(LOG_ERR, "Error opening %s for %s: %s\n", req->pathname, req->remote_ip_addr, strerror(errno_save)); errno = errno_save; if (errno == ENOENT) send_r_not_found(req); else if (errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; #ifdef GUNZIP } close(data_fd); req->response_status = R_REQUEST_OK; if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_content_type(req); print_last_modified(req); req_write(req, "\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; if (req->pathname) free(req->pathname); req->pathname = strdup(buf); return init_cgi(req); /* 1 - OK, 2 - die */ #endif } fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { /* directory */ close(data_fd); /* close dir */ if (req->pathname[strlen(req->pathname) - 1] != '/') { char buffer[3 * MAX_PATH_LENGTH + 128]; if (server_port != 80) sprintf(buffer, "http://%s:%d%s/", req->host?req->host:server_name, server_port, req->request_uri); else sprintf(buffer, "http://%s%s/", req->host?req->host:server_name, req->request_uri); send_redirect_perm(req, buffer); return 0; } data_fd = get_dir(req, &statbuf); /* updates statbuf */ if (data_fd == -1) /* couldn't do it */ return 0; /* errors reported by get_dir */ else if (data_fd == 0) return 1; } if (req->if_modified_since && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } req->filesize = statbuf.st_size; req->last_modified = statbuf.st_mtime; if (req->method == M_HEAD) { send_r_request_ok(req); close(data_fd); return 0; } /* MAP_OPTIONS: see compat.h */ req->data_mem = mmap(0, req->filesize, #ifdef USE_NLS PROT_READ|PROT_WRITE #else PROT_READ #endif , MAP_OPTIONS,data_fd, 0); close(data_fd); /* close data file */ if ((long) req->data_mem == -1) { boa_perror(req, "mmap"); return 0; } send_r_request_ok(req); /* All's well */ { int bob; bob = BUFFER_SIZE - req->buffer_end; if (bob > 0) { if (bob > req->filesize - req->filepos) bob = req->filesize - req->filepos; memcpy(req->buffer + req->buffer_end, req->data_mem + req->filepos, bob); req->buffer_end += bob; req->filepos += bob; } } if (req->filepos == req->filesize) { req->status = CLOSE; return 0; /* done! */ } /* We lose statbuf here, so make sure response has been sent */ return 1; }
int init_get(request * req) { int data_fd; struct stat statbuf; data_fd = open(req->pathname, O_RDONLY); if (data_fd == -1) { /* cannot open */ /* it's either a gunzipped file or a directory */ #ifdef GUNZIP char gzip_pathname[MAX_PATH_LENGTH]; int len; len = strlen(req->pathname); memcpy(gzip_pathname, req->pathname, len); memcpy(gzip_pathname + len, ".gz", 3); gzip_pathname[len + 3] = '\0'; data_fd = open(gzip_pathname, O_RDONLY); if (data_fd == -1) { #endif int errno_save = errno; log_error_doc(req); errno = errno_save; perror("document open"); errno = errno_save; if (errno == ENOENT) send_r_not_found(req); else if (errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; #ifdef GUNZIP } close(data_fd); req->response_status = R_REQUEST_OK; if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_content_type(req); print_last_modified(req); req_write(req, "\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; if (req->pathname) free(req->pathname); req->pathname = strdup(gzip_pathname); return init_cgi(req); #endif } fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { /* directory */ close(data_fd); /* close dir */ if (req->pathname[strlen(req->pathname) - 1] != '/') { char buffer[3 * MAX_PATH_LENGTH + 128]; if (server_port != 80) sprintf(buffer, "http://%s:%d%s/", server_name, server_port, req->request_uri); else sprintf(buffer, "http://%s%s/", server_name, req->request_uri); send_redirect_perm(req, buffer); return 0; } data_fd = get_dir(req, &statbuf); /* updates statbuf */ if (data_fd == -1) /* couldn't do it */ return 0; /* errors reported by get_dir */ else if (data_fd <= 1) /* data_fd == 0 -> close it down, 1 -> continue */ return data_fd; /* else, data_fd contains the fd of the file... */ } if (req->if_modified_since && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } req->filesize = statbuf.st_size; req->last_modified = statbuf.st_mtime; if (req->method == M_HEAD) { send_r_request_ok(req); close(data_fd); return 0; } if (req->filesize > MAX_FILE_MMAP) { send_r_request_ok(req); /* All's well */ req->status = PIPE_READ; req->cgi_status = CGI_BUFFER; req->data_fd = data_fd; req_flush(req); /* this should *always* complete due to the size of the I/O buffers */ req->header_line = req->header_end = req->buffer; return 1; } req->mmap_entry_var = find_mmap(data_fd, &statbuf); if (req->mmap_entry_var == NULL) { send_r_error(req); close(data_fd); return 0; } req->data_mem = req->mmap_entry_var->mmap; close(data_fd); /* close data file */ if ((long) req->data_mem == -1) { boa_perror(req, "mmap"); return 0; } send_r_request_ok(req); /* All's well */ { /* combine first part of file with headers */ int bob; bob = BUFFER_SIZE - req->buffer_end; /* bob is now how much the buffer can hold * after the headers */ if (bob > 0) { if (bob > req->filesize) bob = req->filesize; memcpy(req->buffer + req->buffer_end, req->data_mem, bob); req->buffer_end += bob; req->filepos += bob; if (req->filesize == req->filepos) { req_flush(req); req->status = DONE; return 1; /* get it flushed next time around if need be */ } } } /* We lose statbuf here, so make sure response has been sent */ return 1; }
int init_get(request * req) { int data_fd, saved_errno; struct stat statbuf; volatile int bytes; data_fd = open(req->pathname, O_RDONLY); saved_errno = errno; #ifdef GUNZIP if (data_fd == -1 && errno == ENOENT) { char gzip_pathname[MAX_PATH_LENGTH]; int len; len = strlen(req->pathname); memcpy(gzip_pathname, req->pathname, len); memcpy(gzip_pathname + len, ".gz", 3); gzip_pathname[len + 3] = '\0'; data_fd = open(gzip_pathname, O_RDONLY); if (data_fd != -1) { close(data_fd); req->response_status = R_REQUEST_OK; if (req->pathname) free(req->pathname); req->pathname = strdup(gzip_pathname); if (!req->pathname) { log_error_time(); perror("strdup"); send_r_error(req); return 0; } if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_content_type(req); print_last_modified(req); req_write(req, "\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } } #endif if (data_fd == -1) { log_error_doc(req); errno = saved_errno; perror("document open"); if (saved_errno == ENOENT) send_r_not_found(req); else if (saved_errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); return 0; } fstat(data_fd, &statbuf); if (S_ISDIR(statbuf.st_mode)) { close(data_fd); if (req->pathname[strlen(req->pathname) - 1] != '/') { char buffer[3 * MAX_PATH_LENGTH + 128]; if (server_port != 80) sprintf(buffer, "http://%s:%d%s/", server_name, server_port, req->request_uri); else sprintf(buffer, "http://%s%s/", server_name, req->request_uri); send_r_moved_perm(req, buffer); return 0; } data_fd = get_dir(req, &statbuf); if (data_fd == -1) return 0; else if (data_fd <= 1) return data_fd; } if (req->if_modified_since && !modified_since(&(statbuf.st_mtime), req->if_modified_since)) { send_r_not_modified(req); close(data_fd); return 0; } req->filesize = statbuf.st_size; req->last_modified = statbuf.st_mtime; if (req->method == M_HEAD || req->filesize == 0) { send_r_request_ok(req); close(data_fd); return 0; } if (req->filesize > MAX_FILE_MMAP) { send_r_request_ok(req); req->status = PIPE_READ; req->cgi_status = CGI_BUFFER; req->data_fd = data_fd; req_flush(req); /* this should *always* complete due to the size of the I/O buffers */ req->header_line = req->header_end = req->buffer; return 1; } if (req->filesize == 0) { send_r_request_ok(req); close(data_fd); return 1; } /* NOTE: I (Jon Nelson) tried performing a read(2) * into the output buffer provided the file data would * fit, before mmapping, and if successful, writing that * and stopping there -- all to avoid the cost * of a mmap. Oddly, it was *slower* in benchmarks. */ req->mmap_entry_var = find_mmap(data_fd, &statbuf); if (req->mmap_entry_var == NULL) { req->buffer_end = 0; if (errno == ENOENT) send_r_not_found(req); else if (errno == EACCES) send_r_forbidden(req); else send_r_bad_request(req); close(data_fd); return 0; } req->data_mem = req->mmap_entry_var->mmap; close(data_fd); if ((long) req->data_mem == -1) { boa_perror(req, "mmap"); return 0; } send_r_request_ok(req); bytes = BUFFER_SIZE - req->buffer_end; /* bytes is now how much the buffer can hold * after the headers */ if (bytes > 0) { if (bytes > req->filesize) bytes = req->filesize; if (sigsetjmp(env, 1) == 0) { handle_sigbus = 1; memcpy(req->buffer + req->buffer_end, req->data_mem, bytes); handle_sigbus = 0; } else { log_error_doc(req); reset_output_buffer(req); send_r_error(req); fprintf(stderr, "%sGot SIGBUS in memcpy!\n", get_commonlog_time()); return 0; } req->buffer_end += bytes; req->filepos += bytes; if (req->filesize == req->filepos) { req_flush(req); req->status = DONE; } } return 1; }
int get_dir(request * req, struct stat *statbuf) { char pathname_with_index[MAX_PATH_LENGTH]; int data_fd; if (directory_index) { strcpy(pathname_with_index, req->pathname); strcat(pathname_with_index, directory_index); /* sprintf(pathname_with_index, "%s%s", req->pathname, directory_index); */ data_fd = open(pathname_with_index, O_RDONLY); if (data_fd != -1) { strcpy(req->request_uri, directory_index); fstat(data_fd, statbuf); return data_fd; } if (errno == EACCES) { send_r_forbidden(req); return -1; } else if (errno != 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); if (data_fd != -1) { 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) { log_error_time(); perror("strdup"); send_r_error(req); return 0; } if (!req->simple) { req_write(req, "HTTP/1.0 200 OK-GUNZIP\r\n"); print_http_headers(req); print_last_modified(req); req_write(req, "Content-Type: "); req_write(req, get_mime_type(directory_index)); req_write(req, "\r\n\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } #endif } if (dirmaker != NULL) { req->response_status = R_REQUEST_OK; SQUASH_KA(req); if (!req->simple) { req_write(req, "HTTP/1.0 200 OK\r\n"); print_http_headers(req); print_last_modified(req); req_write(req, "Content-Type: text/html\r\n\r\n"); req_flush(req); } if (req->method == M_HEAD) return 0; return init_cgi(req); } else if (cachedir) { return get_cachedir_file(req, statbuf); } else { send_r_forbidden(req); return -1; } }