Ejemplo n.º 1
0
/*Setting BT files to Download
  *
  */
 void formBTFileSetting(request *wp, char *path, char *query)
{	
	char *strptr;
	char *filestr;
	char *nextwebpage;
	int len;
	int clientindex;
	char tmpbuf[128];
	
	nextwebpage=req_get_cstream_var(wp, ("nextwebpage"),"");
	strptr=req_get_cstream_var(wp,("clientindex"),"");
	if(strptr)
		clientindex=atoi(strptr);
	/*get fileindex*/
	filestr=req_get_cstream_var(wp,("selectedfiles"),"");
	/*get client index*/
	strptr=req_get_cstream_var(wp,("selectednum"),"");
	if(strptr)
		len=atoi(strptr);
	/*call setfile function*/
	bt_setfiles(clientindex, len,filestr);

	/*take a break ~!~*/
	sleep(1);
	strcpy(tmpbuf,nextwebpage);
	sprintf(tmpbuf+strlen(tmpbuf),"?ctorrent=%d",clientindex);
	send_redirect_perm(wp,tmpbuf);
}
Ejemplo n.º 2
0
/*New BT Torrent*/
void formBTNewTorrent(request *wp, char *path, char *query)
{
	char filepath[128];
	char *strptr;
	char *filename;
	char *nextwebpage;
	nextwebpage=req_get_cstream_var(wp, "submit-url","");
	strptr=req_get_cstream_var(wp,("filename"),"");
	char_replace(strptr,'\\','/');
	filename=strrchr(strptr, '/');
	if(filename == NULL)
	{
		printf("ERROR, filename NULL\n");
		return;
	}
	//printf("filename %s \n",filename);
	if(!apmib_get(MIB_BT_UPLOAD_DIR,filepath))
	{
		ERR_MSG("Get seeds directory failed");
		return;
	}
	if(!dirExits(filepath))
	{
		ERR_MSG("Seeds Directory Not Exists");
		return;
	}
	strcat(filepath,filename);
	//printf("filepath %s\n",filepath);
	bt_saveTorrentfile(filepath,wp->post_data, wp->post_data_len);
	send_redirect_perm(wp,nextwebpage);
}
Ejemplo n.º 3
0
/* Down Up Dir and Download Limit Upload limt and refresh time
  *Fiv MIB Save To Flash
  *Shell Script should call the dctcs(need to check dir exits)
  *
  */
void formBTBasicSetting(request *wp, char *path, char *query)
{
	char *downdir;
	char *updir;
	char *strptr;
	char *nextwebpage;
	int ulimit;
	int dlimit;
	int refreshtime;
	int enabled;
	int pid;
	char tmpBuf[256];
	nextwebpage=req_get_cstream_var(wp, ("nextwebpage"),"");
	downdir=req_get_cstream_var(wp, ("btdownloaddir"),"");
	updir=req_get_cstream_var(wp, ("btuploaddir"),"");
	char_replace(downdir,'\\', '/');
	char_replace(updir,'\\', '/');
	if(!dirExits(downdir) ||!dirExits(updir))
	{
		ERR_MSG("Directory Not Exists!!!");
		return;
	}
	apmib_set(MIB_BT_UPLOAD_DIR,updir);
	apmib_set(MIB_BT_DOWNLOAD_DIR,downdir);
	strptr=req_get_cstream_var(wp, ("totalulimit"),"");
	if(strptr)
		ulimit=atoi(strptr);
	apmib_set(MIB_BT_TOTAL_ULIMIT,&ulimit);
	strptr=req_get_cstream_var(wp, ("totaldlimit"),"");
	if(strptr)
		dlimit=atoi(strptr);
	apmib_set(MIB_BT_TOTAL_DLIMIT,&dlimit);
	strptr=req_get_cstream_var(wp, ("refreshtime"),"");
	if(strptr)
		refreshtime=atoi(strptr);
	apmib_set(MIB_BT_REFRESH_TIME,&refreshtime);
	strptr=req_get_cstream_var(wp, ("bt_enabled"),"");
	if(strptr)
		enabled=atoi(strptr);
	apmib_set(MIB_BT_ENABLED,&enabled);
	
	/*Save to flash*/
	apmib_update(CURRENT_SETTING);

	/*run dctcs shell*/
#ifndef NO_ACTION
	pid = fork();
        if (pid) {
	      	waitpid(pid, NULL, 0);
	}
        else if (pid == 0) {
		snprintf(tmpBuf, 100, "%s/%s", _CONFIG_SCRIPT_PATH, _BT_SCRIPT_PROG);
		execl(tmpBuf, _BT_SCRIPT_PROG, NULL);
             exit(1);
        }
#endif
	send_redirect_perm(wp, nextwebpage);
}
Ejemplo n.º 4
0
/*Show Bt Torrents and add/del/update.... 
  *
  */
void formBTClientSetting(request *wp, char *path, char *query)
{
	char *strptr;
	char *clientptr;
	char *tiptr;
	char *operation;
	char *nextwebpage;
	int index;
	nextwebpage=req_get_cstream_var(wp, ("nextwebpage"),"");
	operation=req_get_cstream_var(wp, ("operation"),"");
	//printf("operation value: %s\n",operation);
	/*get index index format /index_1/index_2/...*/
	clientptr=req_get_cstream_var(wp,("clientsindex"),"");
	tiptr=req_get_cstream_var(wp,("torrentsindex"),"");
	//printf("clientptr value: %s\n",clientptr);
	//printf("tiptr value: %s\n",tiptr);
	/*start del should use tiptr*/
	/*pause update adn quit shoud use clientptr*/
	/*start*/
	if(!strcmp(operation,"start"))
	{	
		/*start only one a time*/
		strptr=tiptr;
		while ((strptr=(char *)getbtclientIndex((unsigned char *)strptr,&index)))
		{
			if(index >= 0)
				bt_startTorrent(index);
		}
	}
	/*pause*/
	else if(!strcmp(operation,"pause"))
	{
		strptr=clientptr;
		while ((strptr=(char *)getbtclientIndex((unsigned char *)strptr,&index)))
		{
			if(index >= 0)
				bt_clientPause(index);
		}
	}
	/*stop*/
	else if(!strcmp(operation,"stop"))
	{
		strptr=clientptr;
		while ((strptr=(char *)getbtclientIndex((unsigned char *)strptr,&index)))
		{
			if(index >= 0)
				bt_clientQuit(index);
		}
	}
	/*update*/
	else if(!strcmp(operation,"update"))
	{
		strptr=clientptr;
		while ((strptr=(char *)getbtclientIndex((unsigned char *)strptr,&index)))
		{
			if(index >= 0)
				bt_clientUpdate(index);
		}
	}
	/*delete. delelte torrent or files*/
	else if(!strcmp(operation,"delete"))
	{
		strptr=tiptr;
		while ((strptr=(char *)getbtclientIndex((unsigned char *)strptr,&index)))
		{
			if(index >= 0)
				bt_deleteTorrent(index,0);
		}
	}
	else if(!strcmp(operation,"deleteallfiles"))
	{
		strptr=clientptr;
		while ((strptr=(char *)getbtclientIndex((unsigned char *)strptr,&index)))
		{
			if(index >= 0)
				bt_deleteTorrent(index,1);
		}
	}
	/*details*/
	else if(!strcmp(operation,"details"))
	{
		
	}
	/*info*/
	else if(!strcmp(operation,"info"))
	{
		
	}
	send_redirect_perm(wp,nextwebpage);
}
Ejemplo n.º 5
0
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;
    }
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}