示例#1
0
static int mod_ffeadcpp_method_handler (request_rec *r)
{
	string port = CastUtil::lexical_cast<string>(r->server->port);

	//signal(SIGSEGV,signalSIGSEGV);
	string content;

	apr_bucket_brigade *bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
	for ( ; ; ) {
		apr_bucket* b ;
		bool done = false;
		ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN);
		for ( b = APR_BRIGADE_FIRST(bb);b != APR_BRIGADE_SENTINEL(bb);b = APR_BUCKET_NEXT(b) )
		{
			size_t bytes ;
			const char* buf = "\0";
			if ( APR_BUCKET_IS_EOS(b) )
			{
				done = true;
			}
			else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ)== APR_SUCCESS )
			{
				content += string(buf, 0, bytes);
			}
		}

		if (done)
		  break;
		else
		  apr_brigade_cleanup(bb) ;
	}
	apr_brigade_destroy(bb) ;

	HttpRequest* hreq= new HttpRequest();
	string cntpath = serverRootDirectory + "web/";
	string webpath = "URL" + cntpath;
	MyReq* req = new MyReq();
	req->r = r;
	req->htreq = hreq;

	apr_table_do(iterate_func, req, r->headers_in, NULL);

	ip_address = hreq->getHeader(HttpRequest::Host);
	string tipaddr = ip_address;
	if(port!="80")
		tipaddr += (":" + port);
	ConfigurationData::getInstance()->ip_address = tipaddr;

	string contret;
	if(content!="")
	{
		contret = hreq->buildRequest("Content",content.c_str());
		fprintf(stderr,contret.c_str());
		fflush(stderr);
	}
	hreq->buildRequest(webpath.c_str(),r->uri);
	hreq->buildRequest("Method",r->method);
	if(r->args != NULL && r->args[0] != '\0')
	{
		hreq->buildRequest("GetArguments",r->args);
	}
	hreq->buildRequest("HttpVersion", r->protocol);

	HttpResponse respo = service(hreq);
	string h1 = respo.generateResponse(hreq->getMethod(), hreq, false);

	for (int var = 0; var < (int)respo.getCookies().size(); var++)
	{
		apr_table_add(r->headers_out, "Set-cookie", respo.getCookies().at(var).c_str());
	}

	r->status_line = respo.getStatusLine().c_str();
	if(respo.getHeader(HttpResponse::ContentType)!="")
	{
		r->content_type = respo.getHeader(HttpResponse::ContentType).c_str();
	}
	r->clength = h1.length();

	fprintf(stderr,"\n\n\n\n--------------------------------------------\n");
	fprintf(stderr,hreq->getUrl().c_str());
	fprintf(stderr,"\n");
	string star =  hreq->toString();
	fprintf(stderr,star.c_str());
	fprintf(stderr,"\n--------------------------------------------\n");
	fprintf(stderr,contret.c_str());
	fflush(stderr);
	fprintf(stderr,"\n\n");
	fprintf(stderr,content.c_str());
	fprintf(stderr,"\n");
	fprintf(stderr,"ip_address = %s", tipaddr.c_str());
	fprintf(stderr,"\n");
	fprintf(stderr,"\n--------------------------------------------\n\n\n\n");
	fflush(stderr);
	fprintf(stderr, h1.c_str());
	fflush(stderr);
	delete hreq;
	delete req;

	if(h1!="")
	{
		ap_rwrite (h1.c_str(), h1.length(), r);
		return OK;
	}
	return OK;
}
示例#2
0
void ServiceTask::run()
{
	//logger << dlib << endl;
	string ip = "invalid session";
	string alldatlg = "\ngot fd from parent";
	SSL *ssl=NULL;
	BIO *sbio=NULL;
	BIO *io=NULL,*ssl_bio=NULL;
	try
	{
		int cntlen = 0;
		char buf[MAXBUFLENM];
		strVec results;
		stringstream ss;
		string temp;
		//int bytes = -1;
		if(isSSLEnabled)
		{
			sbio=BIO_new_socket(fd,BIO_NOCLOSE);
			ssl=SSL_new(ctx);
			SSL_set_bio(ssl,sbio,sbio);

			io=BIO_new(BIO_f_buffer());
			ssl_bio=BIO_new(BIO_f_ssl());
			BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE);
			BIO_push(io,ssl_bio);

			int r = SSL_accept(ssl);
			cout << r << endl;
			int bser = SSL_get_error(ssl,r);
			cout << bser << endl;
			if(r<=0)
			{
				sslHandler.error_occurred((char*)"SSL accept error",fd,ssl);
				return;
			}


			int er=-1;
			bool flag = true;
			while(flag)
			{
				er = BIO_gets(io,buf,BUFSIZZ-1);
				cout << er << endl;
				int bser = SSL_get_error(ssl,er);
				cout << bser << endl;
				switch(bser)
				{
					case SSL_ERROR_WANT_READ:
					{
						logger << "more to read error" << endl;
						break;
					}
					case SSL_ERROR_WANT_WRITE:
					{
						logger << "more to write error" << endl;
						break;
					}
					case SSL_ERROR_NONE:
					{
						break;
					}
					case SSL_ERROR_ZERO_RETURN:
					{
						sslHandler.error_occurred((char*)"SSL error problem",fd,ssl);
						if(io!=NULL)BIO_free(io);
						return;
					}
					default:
					{
						sslHandler.error_occurred((char*)"SSL read problem",fd,ssl);
						if(io!=NULL)BIO_free(io);
						return;
					}
				}
				ss << buf;
				//logger <<buf <<endl;
				if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n"))
					break;
				string temp(buf);
				if(temp=="")continue;
				temp = temp.substr(0,temp.length()-1);
				results.push_back(temp);
				//logger << temp <<endl;
				if(temp.find("Content-Length:")!=string::npos)
				{
					std::string cntle = temp.substr(temp.find(": ")+2);
					cntle = cntle.substr(0,cntle.length()-1);
					//logger << "contne-length="<<cntle <<endl;
					try
					{
						cntlen = CastUtil::lexical_cast<int>(cntle);
					}
					catch(const char* ex)
					{
						logger << "bad lexical cast" <<endl;
					}
				}
				memset(&buf[0], 0, sizeof(buf));
			}
		}
		else
		{
			int er=-1;
			bool flag = true;
			sbio=BIO_new_socket(fd,BIO_CLOSE);
			io=BIO_new(BIO_f_buffer());
			BIO_push(io,sbio);
			logger << "into run method" << endl;
			while(flag)
			{
				er = BIO_gets(io,buf,BUFSIZZ-1);
				if(er==0)
				{
					close(fd);
					logger << "\nsocket closed before being serviced" <<flush;
					return;
				}
				ss << buf;
				if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n") || er<0)
					break;
				string temp(buf);
				temp = temp.substr(0,temp.length()-1);
				results.push_back(temp);
				//logger << temp <<endl;
				if(temp.find("Content-Length:")!=string::npos)
				{
					std::string cntle = temp.substr(temp.find(": ")+2);
					cntle = cntle.substr(0,cntle.length()-1);
					//logger << "contne-length="<<cntle <<endl;
					try
					{
						cntlen = CastUtil::lexical_cast<int>(cntle);
					}
					catch(const char* ex)
					{
						logger << "bad lexical cast" <<endl;
					}
				}
				memset(&buf[0], 0, sizeof(buf));
			}
		}

		ss.clear();
		if(isSSLEnabled && cntlen>0)
		{
			int er=-1;
			if(cntlen>0)
			{
				//logger << "reading conetnt " << cntlen << endl;
				er = BIO_read(io,buf,cntlen);
				switch(SSL_get_error(ssl,er))
				{
					case SSL_ERROR_NONE:
						cntlen -= er;
						break;
					case SSL_ERROR_ZERO_RETURN:
					{
						sslHandler.error_occurred((char*)"SSL error problem",fd,ssl);
						if(io!=NULL)BIO_free(io);
						return;
					}
					default:
					{
						sslHandler.error_occurred((char*)"SSL read problem",fd,ssl);
						if(io!=NULL)BIO_free(io);
						return;
					}
				}
				string temp(buf);
				results.push_back("\r");
				results.push_back(temp);
				//logger <<buf <<endl;
				memset(&buf[0], 0, sizeof(buf));
			}
		}
		else if(cntlen>0)
		{
			int er=-1;
			if(cntlen>0)
			{
				//logger << "reading conetnt " << cntlen << endl;
				er = BIO_read(io,buf,cntlen);
				if(er==0)
				{
					close(fd);
					logger << "\nsocket closed before being serviced" <<flush;
					return;
				}
				else if(er>0)
				{
					string temp(buf);
					results.push_back("\r");
					results.push_back(temp);
					//logger << temp <<endl;
					memset(&buf[0], 0, sizeof(buf));
				}
			}
		}
		alldatlg += "--read data";
		map<string,string> params1 = *params;
		string webpath = serverRootDirectory + "web/";
		HttpRequest* req= new HttpRequest(results,webpath);
		//logger << req->toString() << endl;

		if(req->getFile()=="")
		{
			logger << req->getFile() << endl;
			req->setFile("index.html");
		}
		if(req->hasCookie())
		{
			logger << "has the session id" << endl;
			if(!configData.sessatserv)
				req->getSession()->setSessionAttributes(req->getCookieInfo());
			else
			{
				string id = req->getCookieInfoAttribute("FFEADID");
				logger << id << endl;
				map<string,string> values = readFromSharedMemeory(id);
				req->getSession()->setSessionAttributes(values);
			}
		}

		if(configData.cntMap[req->getCntxt_name()]!="true")
		{
			req->setCntxt_name("default");
			req->setCntxt_root(webpath+"default");
			req->setUrl(webpath+"default"+req->getActUrl());
		}
		//logger << req->getCntxt_name() << req->getCntxt_root() << req->getUrl() << endl;

		if(configData.appMap[req->getCntxt_name()]!="false")
		{
			if(dlib == NULL)
			{
				cerr << dlerror() << endl;
				exit(-1);
			}
			string meth1 = (req->getCntxt_name()+"checkRules");
			string path1;
			void *mkr1 = dlsym(dlib, meth1.c_str());
			if(mkr1!=NULL)
			{
				typedef string (*DCPPtr1) (string,HttpSession);
				DCPPtr1 f =  (DCPPtr1)mkr1;
				path1 = f(req->getUrl(),*(req->getSession()));
				//logger << path1 << flush;
				if(path1=="FAILED")
				{
					req->setUrl("");
				}
				else if(path1!="" && path1!=req->getUrl())
				{
					req->setUrl(path1);
				}
			}
		}

		HttpResponse res;
		string ext = getFileExtension(req->getUrl());
		vector<unsigned char> test;
		string content;
		string claz;
		bool isoAuthRes = false;
		long sessionTimeoutVar = configData.sessionTimeout;
		bool isContrl = securityHandler.handle(configData.ip_address, req, res, configData.securityObjectMap, sessionTimeoutVar, dlib, configData.cntMap);

		filterHandler.handleIn(req, res, configData.filterMap, dlib, ext);

		if(!isContrl)
		{
			isContrl = authHandler.handle(configData.autMap, configData.autpattMap, req, res, configData.filterMap, dlib, ext);
		}
		string pthwofile = req->getCntxt_name()+req->getActUrl();
		if(req->getCntxt_name()!="default" && configData.cntMap[req->getCntxt_name()]=="true")
		{
			pthwofile = req->getActUrl();
		}
		if(!isContrl)
		{
			isContrl = controllerHandler.handle(req, res, configData.urlpattMap, configData.mappattMap, dlib, ext,
					configData.rstCntMap, configData.mapMap, configData.urlMap, pthwofile);
		}

		/*After going through the controller the response might be blank, just set the HTTP version*/
		res.setHttpVersion(req->getHttpVersion());
		//logger << req->toString() << endl;
		if(req->getMethod()!="TRACE")
		{
			if(isContrl)
			{

			}
			else if(ext==".form")
			{
				formHandler.handle(req, res, configData.formMap, dlib);
			}
			else if((req->getContent_type().find("application/soap+xml")!=string::npos || req->getContent_type().find("text/xml")!=string::npos)
					&& (req->getContent().find("<soap:Envelope")!=string::npos || req->getContent().find("<soapenv:Envelope")!=string::npos)
					&& configData.wsdlmap[req->getFile()]==req->getCntxt_name())
			{
				soapHandler.handle(req, res, dlib, configData.props[".xml"]);
			}
			else
			{
				bool cntrlit = scriptHandler.handle(req, res, configData.handoffs, dlib, ext, configData.props);
				logger << "html page requested" <<endl;
				if(cntrlit)
				{

				}
				else
				{
					cntrlit = extHandler.handle(req, res, dlib, configData.resourcePath, configData.tmplMap, configData.vwMap, ext, configData.props);
				}
				if(!cntrlit && ext==".fview")
				{
					content = fviewHandler.handle(req, res, configData.fviewmap);
				}
				else
				{
					if(res.getContent_str()=="")
						content = getContentStr(req->getUrl(),configData.lprops[req->getDefaultLocale()],ext);
					else
						content = res.getContent_str();
				}
				if(content.length()==0)
				{
					res.setStatusCode("404");
					res.setStatusMsg("Not Found");
					//res.setContent_len(CastUtil::lexical_cast<string>(0));
				}
				else
				{
					res.setStatusCode("200");
					res.setStatusMsg("OK");
					if(res.getContent_type()=="")res.setContent_type(configData.props[ext]);
					res.setContent_str(content);
					//res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
					//sess.setAttribute("CURR",req->getUrl());
				}
			}

			filterHandler.handleOut(req, res, configData.filterMap, dlib, ext);
		}

		alldatlg += "--processed data";
		string h1;
		bool sessionchanged = !req->hasCookie();
		sessionchanged |= req->getSession()->isDirty();
		if(req->getConnection()!="")
			res.setConnection("close");
		createResponse(res,sessionchanged,req->getSession()->getSessionAttributes(),req->getCookieInfoAttribute("FFEADID"), sessionTimeoutVar, configData.sessatserv);
		//Head should behave exactly as Get but there should be no entity body
		if(req->getMethod()=="HEAD")
		{
			h1 = res.generateHeadResponse();
		}
		else if(req->getMethod()=="OPTIONS")
		{
			h1 = res.generateOptionsResponse();
		}
		else if(req->getMethod()=="TRACE")
		{
			h1 = res.generateTraceResponse(req);
		}
		else
		{
			h1 = res.generateResponse();
		}
		//logger << h1 << endl;
		if(isSSLEnabled)
		{
			int r;
			/* Now perform renegotiation if requested */
			if(configData.client_auth==CLIENT_AUTH_REHANDSHAKE){
			  SSL_set_verify(ssl,SSL_VERIFY_PEER |
				SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);

			  /* Stop the client from just resuming the
				 un-authenticated session */
			  SSL_set_session_id_context(ssl,
				(const unsigned char*)&SSLHandler::s_server_auth_session_id_context,
				sizeof(SSLHandler::s_server_auth_session_id_context));

			  if(SSL_renegotiate(ssl)<=0)
			  {
				  sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl);
				  if(io!=NULL)BIO_free(io);
				  return;
			  }
			  if(SSL_do_handshake(ssl)<=0)
			  {
				  sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl);
				  if(io!=NULL)BIO_free(io);
				  return;
			  }
			  ssl->state=SSL_ST_ACCEPT;
			  if(SSL_do_handshake(ssl)<=0)
			  {
				  sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl);
				  if(io!=NULL)BIO_free(io);
				  return;
			  }
			}
			if((r=BIO_puts(io,h1.c_str()))<=0)
			{
				  sslHandler.error_occurred((char*)"send failed",fd,ssl);
				  if(io!=NULL)BIO_free(io);
				  return;
			}
			if((r=BIO_flush(io))<0)
			{
				  sslHandler.error_occurred((char*)"Error flushing BIO",fd,ssl);
				  if(io!=NULL)BIO_free(io);
				  return;
			}
			sslHandler.closeSSL(fd,ssl,io);
		}
		else
		{
			int size;
			if ((size=send(fd,&h1[0] , h1.length(), 0)) == -1)
				logger << "send failed" << flush;
			else if(size==0)
			{
				close(fd);
				memset(&buf[0], 0, sizeof(buf));
				logger << "socket closed for writing" << flush;
				return;
			}

			if(io!=NULL)BIO_free_all(io);
		}
		close(fd);
		memset(&buf[0], 0, sizeof(buf));
		ss.clear();

		//Logger::info("got new connection to process\n"+req->getFile()+" :: " + res.getStatusCode() + "\n"+req->getCntxt_name() + "\n"+req->getCntxt_root() + "\n"+req->getUrl());
		delete req;
		logger << alldatlg << "--sent data--DONE" << flush;
		//sessionMap[sessId] = sess;
	}
	catch(...)
	{
		logger << "Standard exception: " << endl;
	}
}
static ngx_int_t ngx_http_ffeadcpp_module_handler_post_read(ngx_http_request_t *r)
{
string cntpath = "";
	cntpath.append(ffeadcpp_path.data, ffeadcpp_path.len);
	cntpath += "/web/";
	HttpRequest* req = new HttpRequest(cntpath);

	//cerr << "FFEAD in ngx_http_ffeadcpp_module_handler " << cntpath << r->uri.data << endl;
    ngx_int_t    rc;
    ngx_buf_t   *b;
    ngx_chain_t  out;

	ngx_list_part_t            *part;
    ngx_table_elt_t            *h;
    ngx_uint_t                  i;

    /*
    Get the first part of the list. There is usual only one part.
    */
    part = &r->headers_in.headers.part;
    h = part->elts;

    /*
    Headers list array may consist of more than one part,
    so loop through all of it
    */
    for (i = 0; /* void */ ; i++) {
        if (i >= part->nelts) {
            if (part->next == NULL) {
                /* The last part, search is done. */
                break;
            }

            part = part->next;
            h = part->elts;
            i = 0;
        }
//	cerr << "header -> " << string(h[i].key.data, h[i].key.len) << " = " << string(h[i].value.data, h[i].value.len) << endl;
	req->buildRequest(string(h[i].key.data, h[i].key.len), string(h[i].value.data, h[i].value.len));
    }

    string content;
	ngx_http_read_input_data(r, content);
	//cerr << "Input Request Data\n " << content << "\n======================\n" << endl;
	//cerr << "URL -> " << string(r->uri.data,r->uri.len) << endl;
	//cerr << "Method -> " << string(r->main->method_name.data, r->main->method_name.len) << endl;
	if(content!="")
	{
		req->buildRequest("Content", content.c_str());
	}
	req->buildRequest("URL",  string(r->uri.data,r->uri.len));
	req->buildRequest("Method", string(r->main->method_name.data, r->main->method_name.len));
	if(r->args.len > 0)
	{
		req->buildRequest("GetArguments", string(r->args.data,r->args.len));
	}
	req->buildRequest("HttpVersion", CastUtil::lexical_cast<string>(r->http_version));

	HttpResponse* respo = new HttpResponse;
	ServiceTask* task = new ServiceTask;
	task->handle(req, respo);
	delete task;
cerr << req->toString() << endl;
	if(respo->isDone()) {
		for (int var = 0; var < (int)respo->getCookies().size(); var++)
		{
			set_custom_header_in_headers_out(r, "Set-Cookie", respo->getCookies().at(var));
		}

		/* allocate a buffer for your response body */
		b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
		if (b == NULL) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}

		/* attach this buffer to the buffer chain */
		out.buf = b;
		out.next = NULL;

		string data = respo->generateResponse(false);
		//cerr << "OUT -> " << data << endl;
		map<string,string>::const_iterator it;
		for(it=respo->getHeaders().begin();it!=respo->getHeaders().end();it++) {
			if(StringUtil::toLowerCopy(it->first)==StringUtil::toLowerCopy(HttpResponse::ContentLength)) {
				r->headers_out.content_length_n = CastUtil::lexical_cast<int>(it->second);
			} else {
				set_custom_header_in_headers_out(r, it->first, it->second);
			}
		}
		//cerr << "done writing headers" << endl;		
/* adjust the pointers of the buffer */
		b->pos = data.c_str();
		b->last = data.length();
		b->memory = 1;    /* this buffer is in memory */
		b->last_buf = 1;  /* this is the last buffer in the buffer chain */

		/* set the status line */
		r->headers_out.status = CastUtil::lexical_cast<int>(respo->getStatusCode());

		delete respo;
		delete req;
		/* send the headers of your response */
		rc = ngx_http_send_header(r);
//cerr << "done sending headers " << rc << " " << NGX_OK  <<" "<<  r->header_only  <<" " << NGX_ERROR << endl;
		if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
	        return rc;
	    }

	    /* send the buffer chain of your response */
	    return ngx_http_output_filter(r, &out);
	} else {
		u_char                    *last, *location;
		size_t                     len;
		ngx_str_t                  path;
		ngx_uint_t                 level;
		ngx_log_t                 *log;
		ngx_open_file_info_t       of;
		ngx_http_core_loc_conf_t  *clcf;

		clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

		log = r->connection->log;

		ngx_memzero(&of, sizeof(ngx_open_file_info_t));
		of.read_ahead = clcf->read_ahead;
		of.directio = clcf->directio;
		of.valid = clcf->open_file_cache_valid;
		of.min_uses = clcf->open_file_cache_min_uses;
		of.errors = clcf->open_file_cache_errors;
		of.events = clcf->open_file_cache_events;

		path.data = req->getUrl().c_str();
		path.len = ngx_strlen(path.data);
		
		delete respo;
		delete req;
		rc = NGX_OK;
		if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}
cerr << string(path.data,path.len) << endl;		
		if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
		        != NGX_OK)
		{
			switch (of.err) {

			case 0:
				rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
				break;
			case NGX_ENOENT:
			case NGX_ENOTDIR:
			case NGX_ENAMETOOLONG:

				level = NGX_LOG_ERR;
				rc = NGX_HTTP_NOT_FOUND;
				break;

			case NGX_EACCES:
	#if (NGX_HAVE_OPENAT)
			case NGX_EMLINK:
			case NGX_ELOOP:
	#endif

				level = NGX_LOG_ERR;
				rc = NGX_HTTP_FORBIDDEN;
				break;

			default:

				level = NGX_LOG_CRIT;
				rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
				break;
			}

			if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
				ngx_log_error(level, log, of.err,
							  "%s \"%s\" faileddddddddddddddd", of.failed, path.data);
			}

			//return rc;
		}
		r->root_tested = !r->error_page;
cerr << "found file" << endl;
		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);

		/*if (of.is_dir) {

			ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");

			ngx_http_clear_location(r);

			r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
			if (r->headers_out.location == NULL) {
				return NGX_HTTP_INTERNAL_SERVER_ERROR;
			}

			len = r->uri.len + 1;

			if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
				location = path.data + clcf->root.len;

				*last = '/';

			} else {
				if (r->args.len) {
					len += r->args.len + 1;
				}

				location = ngx_pnalloc(r->pool, len);
				if (location == NULL) {
					return NGX_HTTP_INTERNAL_SERVER_ERROR;
				}

				last = ngx_copy(location, r->uri.data, r->uri.len);

				*last = '/';

				if (r->args.len) {
					*++last = '?';
					ngx_memcpy(++last, r->args.data, r->args.len);
				}
			}
			*/
			/*
			 * we do not need to set the r->headers_out.location->hash and
			 * r->headers_out.location->key fields
			 */

			/*r->headers_out.location->value.len = len;
			r->headers_out.location->value.data = location;

			return NGX_HTTP_MOVED_PERMANENTLY;
		}*/

	#if !(NGX_WIN32) /* the not regular files are probably Unix specific */

		if (!of.is_file) {
			ngx_log_error(NGX_LOG_CRIT, log, 0,
						  "\"%s\" is not a regular file", path.data);

			rc = NGX_HTTP_NOT_FOUND;
		}

	#endif

	/*	if (r->method == NGX_HTTP_POST) {
			return NGX_HTTP_NOT_ALLOWED;
		}*/

		if (rc != NGX_OK) {
			r->headers_out.status = rc;
			ngx_http_send_header(r);
			return ngx_http_send_special (r, NGX_HTTP_LAST);
		}		

		/*rc = ngx_http_discard_request_body(r);

		if (rc != NGX_OK) {
			return rc;
		}*/

		log->action = "sending response to client";

		r->headers_out.status = NGX_HTTP_OK;
		r->headers_out.content_length_n = of.size;
		r->headers_out.last_modified_time = of.mtime;

		/*if (ngx_http_set_etag(r) != NGX_OK) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}*/

		if (ngx_http_set_content_type(r) != NGX_OK) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}

		if (r != r->main && of.size == 0) {
			return ngx_http_send_header(r);
		}

		r->allow_ranges = 1;

		/* we need to allocate all before the header would be sent */

		b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
		if (b == NULL) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}

		b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
		if (b->file == NULL) {
			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}

		rc = ngx_http_send_header(r);

		if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
			return rc;
		}

		b->file_pos = 0;
		b->file_last = of.size;

		b->in_file = b->file_last ? 1: 0;
		b->last_buf = (r == r->main) ? 1: 0;
		b->last_in_chain = 1;

		b->file->fd = of.fd;
		b->file->name = path;
		b->file->log = log;
		b->file->directio = of.is_directio;

		out.buf = b;
		out.next = NULL;

		//return ngx_http_output_filter(r, &out);	
		ngx_http_finalize_request(r, ngx_http_output_filter(r, &out));return NGX_DONE;
		/*cerr << req->getUrl() << " " << cntpath << endl; 
		cntpath = cntpath.substr(0, cntpath.length()-1);
		string rurl = req->getUrl();
		StringUtil::replaceAll(cntpath, "//", "/");
		StringUtil::replaceFirst(rurl, cntpath, "");
		cerr << req->getUrl() << " " << cntpath <<  " " << rurl << endl;
		ngx_str_t nuri;
		nuri.data = rurl.c_str();
		nuri.len = ngx_strlen(nuri.data);
		return ngx_http_internal_redirect(r, &nuri, NULL);*/
	}
}