Exemple #1
0
wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, int contentLength, SecBuffer* ntlmToken)
{
	wStream* s;
	HttpRequest* request;
	char* base64NtlmToken = NULL;

	request = http_request_new();

	if (ntlmToken)
		base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);

	http_request_set_method(request, method);

	request->ContentLength = contentLength;
	http_request_set_uri(request, http->URI);

	if (base64NtlmToken)
	{
		http_request_set_auth_scheme(request, "NTLM");
		http_request_set_auth_param(request, base64NtlmToken);
	}

	s = http_request_write(http, request);
	http_request_free(request);

	free(base64NtlmToken);

	return s;
}
Exemple #2
0
struct task*
create_task(downloader *dler, const char *url, const char *fullname)
{
	struct task *task = (struct task*)malloc(sizeof(struct task));
	
	task->dler          = dler;
	task->next          = dler->tasks;
	dler->tasks         = task;

	task->head_request  = http_request_new(task);

	task->name          = strdup(fullname);
	task->cur_size      = 0;

	task->blocks        = NULL;

	task->start_time    = uv_now(dler->mainloop);
	task->consumed_time = 0;

	task->last_step_time = task->start_time;
	task->last_step_size = task->cur_size;

	if (strncmp(url, "http://", 7) == 0) {
		task->url = http_parse_url(url);
	} else {
		int   len     = strlen(url);
		char *new_url = (char*)calloc(1, len + 7 + 1);
		memcpy(new_url, "http://", 7);
		memcpy(new_url + 7, url, len);

		task->url = http_parse_url(new_url);

		free(new_url);
	}

	if (task->url == NULL) {
		printf("parse url failed\n");
		exit(-1);
	}

	/* change host to a zero-terminated string for uv_getaddrinfo() */
	uv_buf_t buf = http_url_get_field(task->url, UF_HOST);
	char *host = (char*)calloc(1, buf.len + 1);
	memcpy(host, buf.base, buf.len);

	struct addrinfo hints;
	hints.ai_family   = PF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags    = 0;

	uv_getaddrinfo_t *getaddrinfo = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t));
	getaddrinfo->data = task;

	uv_getaddrinfo(dler->mainloop, getaddrinfo, on_resolved, host, NULL, &hints);

	free(host);

	return task;
}
Exemple #3
0
wStream* rdg_build_http_request(rdpRdg* rdg, char* method)
{
	wStream* s;
	HttpRequest* request = NULL;
	SecBuffer* ntlmToken = NULL;
	char* base64NtlmToken = NULL;

	assert(method != NULL);

	request = http_request_new();

	if (!request)
		return NULL;

	http_request_set_method(request, method);
	http_request_set_uri(request, rdg->http->URI);

	if (!request->Method || !request->URI)
		return NULL;

	if (rdg->ntlm)
	{
		ntlmToken = rdg->ntlm->outputBuffer;

		if (ntlmToken)
			base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);

		if (base64NtlmToken)
		{
			http_request_set_auth_scheme(request, "NTLM");
			http_request_set_auth_param(request, base64NtlmToken);

			free(base64NtlmToken);

			if (!request->AuthScheme || !request->AuthParam)
				return NULL;
		}
	}

	if (rdg->state == RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED)
	{
		http_request_set_transfer_encoding(request, "chunked");
	}

	s = http_request_write(rdg->http, request);
	http_request_free(request);

	if (s)
		Stream_SealLength(s);

	return s;
}
static void http_client_loop(struct http_thread_env *hte)
{
	gchar *line = NULL;
	gsize nbyte = 0;
	HttpRequest *req = NULL;
	gint n;

	while ((n = getline(&line, &nbyte, hte->fp)) >= 0) {
		line[n] = '\0';
		if (n && line[n - 1] == '\n') line[--n] = '\0';
		if (n && line[n - 1] == '\r') line[--n] = '\0';

		if (n) mbb_log_lvl(MBB_LOG_HTTP, "recv: %s", line);

		if (req == NULL) {
			if ((req = http_request_new(line)) == NULL) {
				push_http_msg(hte, MBB_MSG_INVALID_HEADER, line);
				break;
			}

			if (! parse_url(req->url, &hte->json, &hte->method)) {
				push_http_error_msg(hte, "invalid url %s", req->url);
				break;
			}
		} else if (n) {
			if (http_request_add_header(req, line) == FALSE) {
				mbb_log_lvl(MBB_LOG_HTTP, "invalid header");
				push_http_msg(hte, MBB_MSG_INVALID_HEADER, line);
				break;
			}
		} else {
			if (req->method == HTTP_METHOD_POST) {
				if (process_http_body(hte, req) == FALSE)
					break;
			}

			process_http(hte, req);
			break;
		}
	}

	if (req != NULL)
		http_request_free(req);

	if (hte->root_tag != NULL) {
		xml_tag_free(hte->root_tag);
		hte->root_tag = NULL;
	}

	g_free(line);
}
gboolean handle_accept( GIOChannel *sock, GIOCondition cond, void *dummy ) {
    GIOChannel *conn;
    http_request *req;
    int fd;

    fd = accept( g_io_channel_unix_get_fd(sock), NULL, NULL );
    g_assert( fd != -1 );

    conn = g_io_channel_unix_new( fd );
    req  = http_request_new( conn );

    g_io_add_watch( conn, G_IO_IN, (GIOFunc) handle_read, req );
    return TRUE;
}
Exemple #6
0
int main(int argc, char* argv[]){
  size_t reqlen;
  HTTPRequest* req;
  const char* test_req;
  
  req = http_request_new();
  test_req ="GET /index.html HTTP/1.1" CRLF\
            "Content-Length: 1" CRLF\
            "A:       B" CRLF\
            "C:          D" CRLF\
            CRLF\
            "x";

  reqlen =  strlen(test_req) - 1;

  //http_request_parse_feed(req, test_req, strlen(test_req));

  
  for(size_t i = 0;  i < reqlen / 9; i+=9){
    http_request_parse_feed(req,test_req,9);
    test_req+=9;
  }
  http_request_parse_feed(req,test_req,reqlen - reqlen / 9);
  
  /*while(*test_req!='\0'){
    http_request_parse_feed(req,test_req,1);
    ++test_req;
    };*/

  printf("method: %d\n, URI:\"%s\"\n, version: %d\n"\
	 "header1: \"%s\": \"%s\"\n"\
	 "header3: \"%s\": %s\n"\
	 "err : %d\n"\
	 "body: %s\n",
	 req->method,
	 req->URI,
	 req->http_version,
	 req->headers[0].name, req->headers[0].value,
	 req->headers[2].name, req->headers[2].value,
	 req->err,
	 req->body);
  
  http_request_free(req);
  exit(EXIT_SUCCESS);
}
Exemple #7
0
wStream* rpc_ntlm_http_request(rdpRpc* rpc, SecBuffer* ntlm_token, int content_length, TSG_CHANNEL channel)
{
	wStream* s;
	HttpContext* http_context;
	HttpRequest* http_request;
	char* base64_ntlm_token = NULL;

	http_request = http_request_new();

	if (ntlm_token)
		base64_ntlm_token = crypto_base64_encode(ntlm_token->pvBuffer, ntlm_token->cbBuffer);

	if (channel == TSG_CHANNEL_IN)
	{
		http_context = rpc->NtlmHttpIn->context;
		http_request_set_method(http_request, "RPC_IN_DATA");
	}
	else if (channel == TSG_CHANNEL_OUT)
	{
		http_context = rpc->NtlmHttpOut->context;
		http_request_set_method(http_request, "RPC_OUT_DATA");
	}
	else
	{
		return NULL;
	}

	http_request->ContentLength = content_length;
	http_request_set_uri(http_request, http_context->URI);

	if (base64_ntlm_token)
	{
		http_request_set_auth_scheme(http_request, "NTLM");
		http_request_set_auth_param(http_request, base64_ntlm_token);
	}

	s = http_request_write(http_context, http_request);
	http_request_free(http_request);

	free(base64_ntlm_token);

	return s;
}
Exemple #8
0
http_request_t *
http_request (const char *url, int port) {
  http_request_t *req = NULL;
  socket_t *sock = NULL;
  char *buf = NULL;
  char *data = NULL;
  size_t len = 0;
  size_t size = 0;
  int rc = 0;

  // init
  sock = sock_tcp_client_new(url, port);
  if (NULL == sock) { return NULL; }

  data = (char *) malloc(sizeof(char) * MAX_REQUEST_BUFFER_SIZE);
  if (NULL == data) {
    sock_free(sock);
    return NULL;
  }

  // connect
  rc = sock_connect(sock);
  if (rc < 0) {
    sock_free(sock);
    return NULL;
  }

  // read
  while ((len = sock_read(sock, buf, MAX_REQUEST_BUFFER_SIZE)) > 0) {
    printf("%s\n", buf);
  }

  req = http_request_new((http_socket_t *) sock, buf);
  if (NULL == req) {
    sock_free(sock);
    return NULL;
  }

  sock_close(sock);

  return NULL;
}
Exemple #9
0
static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method,
                                       const char* transferEncoding)
{
	wStream* s = NULL;
	HttpRequest* request = NULL;
	assert(method != NULL);
	request = http_request_new();

	if (!request)
		return NULL;

	http_request_set_method(request, method);
	http_request_set_uri(request, rdg->http->URI);

	if (!request->Method || !request->URI)
		goto out;

	if (rdg->ntlm)
	{
		if (!rdg_set_ntlm_auth_header(rdg->ntlm, request))
			goto out;
	}

	if (transferEncoding)
	{
		http_request_set_transfer_encoding(request, transferEncoding);
	}

	s = http_request_write(rdg->http, request);
out:
	http_request_free(request);

	if (s)
		Stream_SealLength(s);

	return s;
}
Exemple #10
0
/* Extract http_pair_t objects from flow's packet_t chain */
int 
flow_extract_http(flow_t *f)
{
	/* check if the flow is carrying HTTP again */
	if( f->http == FALSE)
		return 1;
		
	/*
	 * Find the actual FIN sequences.
	 */
	seq_t	*seq = f->order->src;
	seq_t	*src_fin_seq = NULL;
	seq_t	*dst_fin_seq = NULL;
	int found = 0;
	
	while(seq != NULL)
	{
		/* Update flow's first byte time.
		 * FBT of flow refers to the payload's FBT.
		 */
		if(seq->pkt != NULL && found == 0)
		{
			found = 1;
			f->fb_sec = seq->cap_sec;
			f->fb_usec = seq->cap_usec;
		}
		
		/*Search the FIN sequence in sequence queue.*/
		if(seq->th_flags & TH_FIN == TH_FIN)
		{
			src_fin_seq = seq;
			break;
		}
		seq = seq->next;
	}
	
	seq = f->order->dst;
	while(seq != NULL)
	{
		/*Search the FIN sequence in sequence queue.*/
		if(seq->th_flags & TH_FIN == TH_FIN)
		{
			dst_fin_seq = seq;
			break;
		}
		seq = seq->next;
	}
	
	/*
	 * Set the client and server FIN sequences.
	 */
	seq_t	*fin_seq = NULL;	/* The actual FIN sequence. */
	u_int8_t	fin_dir = 0;	/* fin_dir:
	 * 0: Not set;
	 * 1: src_fin_seq is used;
	 * 2: dst_fin_seq is used;
	 */
	
	if (src_fin_seq != NULL && dst_fin_seq == NULL)
	{
		fin_seq = src_fin_seq;
		fin_dir = 1;
	}
	else if (src_fin_seq == NULL && dst_fin_seq != NULL)
	{
		fin_seq = dst_fin_seq;
		fin_dir = 2;
	}
	else if (src_fin_seq != NULL && dst_fin_seq != NULL)
	{
		fin_seq = src_fin_seq;
		fin_dir = 1;
		if(compare_sequence_time(src_fin_seq, dst_fin_seq) == 1)
		{
			fin_seq = dst_fin_seq;
			fin_dir = 2;
		}
	}
	else
	{
		fin_seq = NULL;
		fin_dir = 0;
	}
	
	/* 
	 * First step: find requests 
	 */
	packet_t *pkt;
	request_t	*req;
	response_t	*rsp;
	int reqn = 0;	// Number of requests.
	int rspn = 0;	// Number of responses.
	
	http_pair_t *new_http = NULL;
	seq_t *seq_next = NULL;	/* for temp */
	seq_t *first_seq = NULL;
	/* Set seq and seq_next */
	seq = f->order->src;
	if( seq != NULL)
	{
		seq_next = seq->next;
	}
	else
	{
		seq_next = NULL;		/* NULL */
	}
	
	if (fin_seq != NULL && seq != NULL)
	{
		/*A FIN packet exists.*/
		while(compare_sequence_time(seq, fin_seq) < 0)
		{
			pkt = seq->pkt;
			if(pkt != NULL && pkt->http == HTTP_REQ)
			{
				/* When a new HTTP request is found,
				 * create a HTTP pair object, then add the object to
				 * flow's HTTP chain.
				 */
				reqn++;
				/* new HTTP pair object*/
				new_http = http_new();
				first_seq = seq;
				new_http->req_fb_sec = seq->cap_sec;
				new_http->req_fb_usec = seq->cap_usec;
				new_http->req_lb_sec = seq->cap_sec;
				new_http->req_lb_usec = seq->cap_usec;
					
				/* Add the object to flow's HTTP chain */
				flow_add_http(f, new_http);
				/* new request object */
				req = http_request_new();
				/* Add the request object to the foregoing HTTP pair object */
				http_add_request(new_http, req);
				/* parse and write values to foregoing request object */
				http_parse_request(req, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl);
			}
			else
			{
				/*Omit the TCP handshake sequences.*/
				if(new_http == NULL)
				{
					seq = seq->next;
					if(seq != NULL)
						seq_next = seq->next;
					else
						break;
					continue;
				}
			}

			if( new_http != NULL )
			{
				if( seq_next == NULL || seq_next == fin_seq || seq_next->pkt != NULL ||\
						compare_sequence_time(seq_next, fin_seq) >= 0 ){
					//assert(seq->nxt_seq != 0);
					if( seq->nxt_seq != 0){
						new_http->req_total_len = seq->nxt_seq - first_seq->seq;
						new_http->req_body_len = 0;
					}
					/*Update flow's last byte time.*/
					if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec))
					{
						f->lb_sec = seq->cap_sec;
						f->lb_usec = seq->cap_usec;
					}
				}
				else
				{
					//assert(seq->seq <= seq_next->seq);
				}
			}
			
			/* Continue to next sequence.*/
			seq = seq->next;
			if(seq != NULL)
				seq_next = seq->next;
			else
				break;
		}
	}
	else
	{
		/* No FIN packet found.*/
		while(seq != NULL)
		{
			pkt = seq->pkt;
			if(pkt != NULL && pkt->http == HTTP_REQ)
			{
				/* When a new HTTP request is found,
				 * create a HTTP pair object, then add the object to
				 * flow's HTTP chain.
				 */
				reqn++;
				/* new HTTP pair object*/
				new_http = http_new();
				first_seq = seq;
				new_http->req_fb_sec = seq->cap_sec;
				new_http->req_fb_usec = seq->cap_usec;
				new_http->req_lb_sec = seq->cap_sec;
				new_http->req_lb_usec = seq->cap_usec;
				
				/* Add the object to flow's HTTP chain */
				flow_add_http(f, new_http);
				/* new request object */
				req = http_request_new();
				/* Add the request object to the foregoing HTTP pair object */
				http_add_request(new_http, req);
				/* parse and write values to foregoing request object */
				http_parse_request(req, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl);
			}
			else
			{
				if(new_http == NULL)
				{
					/*Omit the TCP handshake sequences.*/
					seq = seq->next;
					if(seq != NULL)
						seq_next = seq->next;
					else
						break;
					continue;
				}
			}
			if( new_http != NULL )
			{
				if( seq_next == NULL || seq_next->pkt != NULL )
				{
					//assert(seq->nxt_seq != 0);
					if( seq->nxt_seq != 0){
						new_http->req_total_len = seq->nxt_seq - first_seq->seq;
						new_http->req_body_len = 0;
					}
					/*Update flow's last byte time.*/
					if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec))
					{
						f->lb_sec = seq->cap_sec;
						f->lb_usec = seq->cap_usec;
					}
				}
				else
				{
					//assert(seq->seq <= seq_next->seq);
				}
			}
			/*Continue to next sequence.*/
			seq = seq->next;
			if(seq != NULL)
				seq_next = seq->next;
			else
				break;
		}
	}

	/* If no responses found, we treat the flow as invalid and stop parsing */
	if(reqn == 0)
		return 1;
		
	/* Second step: find responses */
	http_pair_t *tmp = f->http_f;
	http_pair_t *found_http = NULL;
	seq = f->order->dst;
	if( seq != NULL)
		seq_next = seq->next;
	else
		seq_next = NULL;		/* NULL */
	if(fin_seq != NULL && seq != NULL){
		/*There is FIN packet.*/
		while(compare_sequence_time(seq, fin_seq) < 0)
		{
			pkt = seq->pkt;
			if ( pkt != NULL && pkt->http == HTTP_RSP)
			{
				/*
				 * Similar to the request parsing, a new response is
				 * added to the first pair without response
				 */
				rspn++;
				/* Try to find the first pair without response */
				while(tmp != NULL)
				{
					if(tmp->response_header == NULL)
						break;
					tmp = tmp->next;
				}
				if(tmp == NULL)
					/* no response empty, then return */
					return 1;
				else
				{
					/*Found!*/
					found_http = tmp;
					first_seq = seq;
					found_http->rsp_fb_sec = seq->cap_sec;
					found_http->rsp_fb_usec = seq->cap_usec;
					rsp = http_response_new();
					http_add_response(found_http, rsp);
					http_parse_response(rsp, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl);
				}
			}
			else
			{
				if(found_http == NULL)
				{
					seq = seq->next;
					if(seq != NULL)
						seq_next = seq->next;
					else
						break;
					continue;
				}
			}

			if ( found_http != NULL )
			{
				/*first_seq != NULL*/
				if( seq_next == NULL || seq_next == fin_seq || seq_next->pkt != NULL ||\
						compare_sequence_time(seq_next, fin_seq) >= 0 )
				{
					found_http->rsp_lb_sec = seq->cap_sec;
					found_http->rsp_lb_usec = seq->cap_usec;
					//assert( seq->nxt_seq != 0 );
					if(seq->nxt_seq != 0){
						found_http->rsp_total_len = seq->nxt_seq - first_seq->seq;
						//printf("%d,%d", found_http->rsp_total_len, found_http->response_header->hdlen);
						//assert(found_http->rsp_total_len >= found_http->response_header->hdlen);
						found_http->rsp_body_len = found_http->rsp_total_len - found_http->response_header->hdlen;
					}
					/*Update flow's last byte time.*/
					if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec))
					{
						f->lb_sec = seq->cap_sec;
						f->lb_usec = seq->cap_usec;
					}
				}
				else
				{
					//assert(seq->seq <= seq_next->seq);
				}
			}

			seq = seq->next;
			if(seq != NULL)
				seq_next = seq->next;
			else
				break;
		}
	}
	else
	{
		/*There is no FIN packet.*/
		while(seq != NULL)
		{
			pkt = seq->pkt;
			if ( pkt != NULL && pkt->http == HTTP_RSP )
			{
				/*
				 * Similar to the request parsing, a new response is
				 * added to the first pair without response
				 */
				rspn++;
				/* Try to find the first pair without response */
				while(tmp != NULL)
				{
					if(tmp->response_header == NULL)
						break;
					tmp = tmp->next;
				}
				if(tmp == NULL)
					/* no response empty, then return */
					return 1;
				else
				{
					/*Found!*/
					found_http = tmp;
					first_seq = seq;
					found_http->rsp_fb_sec = seq->cap_sec;
					found_http->rsp_fb_usec = seq->cap_usec;
					rsp = http_response_new();
					http_add_response(found_http, rsp);
					http_parse_response(rsp, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl);
				}
			}
			else
			{
				if(found_http == NULL)
				{
					seq = seq->next;
					if(seq != NULL)
						seq_next = seq->next;
					else
						break;
					continue;
				}
			}

			if ( found_http != NULL )
			{
				/*first_seq != NULL*/
				if( seq_next == NULL || seq_next->pkt != NULL )
				{
					found_http->rsp_lb_sec = seq->cap_sec;
					found_http->rsp_lb_usec = seq->cap_usec;
					//assert( seq->nxt_seq != 0 );
					if(seq->nxt_seq != 0){
						found_http->rsp_total_len = seq->nxt_seq - first_seq->seq;	
						assert(found_http->rsp_total_len >= found_http->response_header->hdlen);
						found_http->rsp_body_len = found_http->rsp_total_len - found_http->response_header->hdlen;
					}
					/*Update flow's last byte time.*/
					if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec))
					{
						f->lb_sec = seq->cap_sec;
						f->lb_usec = seq->cap_usec;
					}
				}
				else
				{
					//assert(seq->seq <= seq_next->seq);
				}
			}

			seq = seq->next;
			if(seq != NULL)
				seq_next = seq->next;
			else
				break;
		}
	}
	return 0;
}
Exemple #11
0
int 
main(int argc, char **argv)
{
  HttpRequest    *req  = NULL;
  int             port = 8000;
  int             c;
  char           *didiwiki_home = NULL;
  int             restore_WikiHelp = 0;
  struct in_addr address;

  /* default values */
  debug = 0; //normal mode
  hostlogin = 0; //host will have to login
  nologin = 0; //users will have to login.
  dosendmail = 0; //don't send systematically email at each registration
  lgindex = 20; //print 20 files before to make a new index box

  /* by default bind server to "0.0.0.0" */
  address.s_addr = inet_addr("0.0.0.0");

  while (1)
  {
    static struct option long_options[] = 
    {
      {"autologin",  no_argument,   0, 'a'},
      {"nologin",  no_argument,     0, 'n'},
      {"debug",  no_argument,       0, 'd'},
      {"version",  no_argument,     0, 'v'},
      {"listen", required_argument, 0, 'l'},
      {"port",   required_argument, 0, 'p'},
      {"home",   required_argument, 0, 'h'},
      {"restore",   no_argument,    0, 'r'},
      {"sendmail",  no_argument,    0, 's'},
      {"index",  required_argument, 0, 'i'},
      {"help",   no_argument,       0,  10 },
      {0, 0, 0, 0}
    };

    /* getopt_long stores the option index here */
    int option_index = 0;
    
    c = getopt_long (argc, argv, "adl:p:h:i:rsv", long_options, &option_index);

    /* detect the end of the options */
    if (c == -1)
    break;

    switch (c)
    {
      case 0:
        break;
      case 'i': //set index length
        lgindex = atoi(optarg);
        if (lgindex==0) lgindex=20;
        fprintf(stderr,"Index length = %i\n",lgindex);
        break;   
      case 'a': //autologin for the localhost
        hostlogin = 1;
        fprintf(stderr,"Localhost is logged in.\n");
        break;
      case 'n': //autologin any user
        nologin = 1;
        fprintf(stderr,"Any user registrered or not will be logged in.\n");
        break;  
      case 'd':
        debug = 1;
        break;      
      case 'v':
        printf("CiWiki alias DidiWiki - version %s\n\n",VERSION);
        return 0;         
      case 'p': //default port is 8000
        port = atoi(optarg);
        break;   
      case 'h': //default home directory is ~/.didiwiki
        didiwiki_home = optarg;
        break;
      case 'l': //listen a inet address
        if(inet_aton(optarg,&address) == 0) 
        {
          fprintf(stderr, "didiwiki: invalid ip address \"%s\"\n", optarg);
          exit(1);
        } else
          address.s_addr = inet_addr(optarg);
        break;
      case 'r': //rewrite Wikihelp page
        restore_WikiHelp=1; 
        break;
      case 's':
        dosendmail= 1;
        break;
      case 10:
        usage();
        break;
      default:
        usage();
    }
  } //end while

  wiki_init(didiwiki_home,restore_WikiHelp);

  if (debug)
  {
    req = http_request_new();   /* reads request from stdin */
  }
  else 
  {
    req = http_server(address, port);    /* forks here */
  }

  wiki_handle_http_request(req);

  return 0;
}
/*
** Implement an HTTP server daemon.
*/
HttpRequest*
http_server(struct in_addr address, int iPort)
{
  int                listener;      /* The server socket */
  int                connection;    /* A socket for each connection */
  fd_set             readfds;       /* Set of file descriptors for select() */
  socklen_t          lenaddr;       /* Length of the inaddr structure */
  int                child;         /* PID of the child process */
  int                nchildren = 0; /* Number of child processes */
  struct timeval     delay;         /* How long to wait inside select() */
  struct sockaddr_in inaddr;        /* The socket address */
  int                reuse = 1;
  int                n = 0;
  char               url_prefix[256];
  int                val; //not used

  /* catch SIGINT */
  (void) signal(SIGINT, sigint);

  /* catch SIGTERM */
  (void) signal(SIGTERM, sigterm);

  memset(&inaddr, 0, sizeof(inaddr));
  inaddr.sin_family = AF_INET;
  inaddr.sin_addr.s_addr = address.s_addr;
  inaddr.sin_port = htons(iPort);
  listener = socket(AF_INET, SOCK_STREAM, 0);

  fprintf(stderr,"DidiWiki firing up ...\n");

  if( listener < 0 )
  {
    fprintf(stderr,"Can't create a socket\n");
    exit(1);
  }

#ifdef SO_REUSEADDR
  setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 
#endif

  while (n < 10)
  {
    fprintf(stderr,"Attempting to bind to %s:%i .. ", inet_ntoa(address), iPort);

    inaddr.sin_port = htons(iPort + n);

    if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0 )
    {
      fprintf(stderr,"Failed! \n");
      n++;
      continue;
    }

    fprintf(stderr,"Success! \n");
    break;
  }

  if (n == 10)
  {
    fprintf(stderr,"Can't bind to any ports, giving up.\n");
    exit(1);
  }

  fprintf(stderr,"DidiWiki Started. Please point your browser at %s:%i\n", inet_ntoa(address), iPort);

  /* log starting information */
  openlog("didiwiki", 0, 0);
  syslog(LOG_LOCAL0|LOG_INFO, "started with PID %d", getpid());

  /* Set DIDIWIKI_URL_PREFIX if not already set - rss uses it */
  snprintf(url_prefix, 256, "%s:%i/", inet_ntoa(address), iPort+n);
  setenv("DIDIWIKI_URL_PREFIX", url_prefix , 0);

  listen(listener,10);
  
  /* Listen undefinitely */
  while( 1 )
  {
    if( nchildren>MAX_PARALLEL )
    {
      /* Slow down if connections are arriving too fast */
      sleep( nchildren-MAX_PARALLEL );
    }

    delay.tv_sec = 60;
    delay.tv_usec = 0;
    FD_ZERO(&readfds);
    FD_SET( listener, &readfds);

    if( select( listener+1, &readfds, 0, 0, &delay) )
    {
      lenaddr = sizeof(inaddr);
      connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
      if( connection>=0 )
      {
        child = fork();
        if( child!=0 )
        {
          if( child>0 ) nchildren++;
          close(connection);
        }
        else
        {
          /* *child*, connect stdin/out to socket */
          /* then return req object for caller to handle */
          close(0);
          val = dup(connection);
          close(1);
          val = dup(connection);
          close(2);
          val = dup(connection);
          close(connection);
          return http_request_new();
        }
	    }
    }
    /* Bury dead children */
    while( waitpid(0, 0, WNOHANG)>0 ) nchildren--;
  }
  /* NOT REACHED */  
  exit(1);
}