Exemplo n.º 1
0
/* Parse a header and fill in any relevant fields in the response structure. */
int http_response_parse_header(struct http_response *response, const char *header)
{
    int code;

    code = http_parse_header(&response->header, header);
    if (code != 0)
        return code;
    code = http_header_get_content_length(response->header, &response->content_length);
    if (code != 0)
        return code;

    return 0;
}
Exemplo n.º 2
0
/**
 *  @return
 *   -1 if a header was invalid (see http status for details)
 *    0 if all headers are successfully handled (end-of-header reached)
 */
int
http_process_headers(http_t *ctx, char *buf, size_t buf_size)
{
  RUNTIME_ASSERT(ctx);
  RUNTIME_ASSERT(HTTP_STATE_HEADERS == ctx->state);
  
  for (;;) {
    char *name, *value;
    
    name = value =  NULL;
    switch (http_parse_header(ctx, buf, buf_size, &name, &value)) {
    case -1:
      DBUG("http_parse_header() failed: %u \"%s\"",
        ctx->status_code, ctx->status_msg);
      return -1;
      
    case 0:
      RUNTIME_ASSERT(HTTP_STATE_BODY == ctx->state);
      return 0;

    case 1:
      break;

    default:
      RUNTIME_ASSERT(0);
      http_set_status(ctx, 500, "Internal Server Error");
      return -1;
    }

    RUNTIME_ASSERT(HTTP_STATE_HEADERS == ctx->state);
    RUNTIME_ASSERT(name);
    RUNTIME_ASSERT(value);

#if 0
    http_log(ctx, "name=\"%s\"; value=\"%s\"", name, value);
#endif
    
    if (0 != http_handle_header(ctx, name, value))
      break;
  }

  return -1;
}
Exemplo n.º 3
0
Arquivo: http.c Projeto: nqv/aranea
int http_parse(struct request_t *self, char *data, int len) {
    char *p;

    /* get request line */
    p = http_parse_request(self, data, len);
    if (p == NULL) {
        return -1;
    }
    len -= p - data;
    data = p;
    /* get other headers until end of the request */
    while ((len > 0) && !((data[0] == '\n')
            || (len >= 2 && data[0] == '\r' && data[1] == '\n'))) {
        p = http_parse_header(self, data, len);
        if (p == NULL) {
            return -1;
        }
        len -= p - data;
        data = p;
    }
    return 0;
}
Exemplo n.º 4
0
int http_parse(int fd, struct http_request *r)
{
    int recvd;
    static char command[HTTP_BUFFER_LEN + 1];
    char *i;
    int newline_machine = 0;
    char *linestart;
    char *bodystart;
    static char linebuf[HTTP_LINE_LEN + 1];
    int linenum;

    if ((recvd = read(fd, (void*)command, HTTP_BUFFER_LEN)) < 0) {
        if (errno == EAGAIN) {
            printf("Eagain\n");
            return recvd;
        }
        perror("recvfrom");
        exit(1);
    }

    if ((recvd == 1 && *((char*)command) == '\0') || (recvd == 0)) {
        return 0;
    }

    command[HTTP_BUFFER_LEN] = '\0';

    linenum = 0;
    linestart = command;
    for (i = command; *i; ++i) {
        switch (newline_machine) {
            case 0: case 2: {
                if (*i == '\r') newline_machine++;
                else newline_machine = 0;
            } break;
            case 1: {
                if (*i == '\n') newline_machine++;
                else newline_machine = 0;
            } break;
            case 3: {
                if (*i == '\n') newline_machine++;
                else newline_machine = 0;
            } break;
            default: {
                newline_machine = 0;
            }
        }
        if (newline_machine == 2) {
            int linelength = i - linestart;
            linelength = linelength < HTTP_LINE_LEN ? linelength : HTTP_LINE_LEN;
            strncpy(linebuf, linestart, i - linestart);
            linebuf[HTTP_LINE_LEN] = '\0';
            if (linenum == 0) {
                if (http_parse_status(r, linebuf) < 0) {
                    printf("Estatus\n");
                    return -1;
                }
            } else {
                if (http_parse_header(r, linebuf) < 0) {
                    printf("Eheader\n");
                    return -1;
                }
            }

            linestart = i + 1;
            linenum++;
        }
        if (newline_machine == 4) {
            bodystart = i + 1;
            if (http_parse_body(r, bodystart) < 0) {
                printf("Ebody\n");
                return -1;
            }
            linenum++;
            break;
        }
    }

    return 0;
}
Exemplo n.º 5
0
/* Return a usable socket descriptor after proxy negotiation, or -1 on any
   error. If any bytes are received through the proxy after negotiation, they
   are written to stdout. */
static int do_proxy_http(void)
{
    struct socket_buffer sockbuf;
    char *request;
    char *status_line, *header;
    char *remainder;
    size_t len;
    int sd, code;
    int n;

    sd = do_connect(SOCK_STREAM);
    if (sd == -1) {
        loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
        return -1;
    }

    status_line = NULL;
    header = NULL;

    /* First try a request with no authentication. */
    request = http_connect_request(&httpconnect, &n);
    if (send(sd, request, n, 0) < 0) {
        loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
        free(request);
        return -1;
    }
    free(request);

    socket_buffer_init(&sockbuf, sd);

    if (http_read_status_line(&sockbuf, &status_line) != 0) {
        loguser("Error reading proxy response Status-Line.\n");
        goto bail;
    }
    code = http_parse_status_line_code(status_line);
    logdebug("Proxy returned status code %d.\n", code);
    free(status_line);
    status_line = NULL;
    if (http_read_header(&sockbuf, &header) != 0) {
        loguser("Error reading proxy response header.\n");
        goto bail;
    }

    if (code == 407 && o.proxy_auth != NULL) {
        struct http_header *h;
        struct http_challenge challenge;

        close(sd);
        sd = -1;

        if (http_parse_header(&h, header) != 0) {
            loguser("Error parsing proxy response header.\n");
            goto bail;
        }
        free(header);
        header = NULL;

        if (http_header_get_proxy_challenge(h, &challenge) == NULL) {
            loguser("Error getting Proxy-Authenticate challenge.\n");
            http_header_free(h);
            goto bail;
        }
        http_header_free(h);

        sd = do_connect(SOCK_STREAM);
        if (sd == -1) {
            loguser("Proxy reconnection failed: %s.\n", socket_strerror(socket_errno()));
            goto bail;
        }

        request = http_connect_request_auth(&httpconnect, &n, &challenge);
        if (request == NULL) {
            loguser("Error building Proxy-Authorization header.\n");
            http_challenge_free(&challenge);
            goto bail;
        }
        logdebug("Reconnection header:\n%s", request);
        if (send(sd, request, n, 0) < 0) {
            loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
            free(request);
            http_challenge_free(&challenge);
            goto bail;
        }
        free(request);
        http_challenge_free(&challenge);

        socket_buffer_init(&sockbuf, sd);

        if (http_read_status_line(&sockbuf, &status_line) != 0) {
            loguser("Error reading proxy response Status-Line.\n");
            goto bail;
        }
        code = http_parse_status_line_code(status_line);
        logdebug("Proxy returned status code %d.\n", code);
        free(status_line);
        status_line = NULL;
        if (http_read_header(&sockbuf, &header) != 0) {
            loguser("Error reading proxy response header.\n");
            goto bail;
        }
    }

    free(header);
    header = NULL;

    if (code != 200) {
        loguser("Proxy returned status code %d.\n", code);
        return -1;
    }

    remainder = socket_buffer_remainder(&sockbuf, &len);
    Write(STDOUT_FILENO, remainder, len);

    return sd;

bail:
    if (sd != -1)
        close(sd);
    if (status_line != NULL)
        free(status_line);
    if (header != NULL)
        free(header);

    return -1;
}
Exemplo n.º 6
0
static void on_read(void *arg)
{
    module_data_t *mod = arg;

    asc_timer_destroy(mod->timeout_timer);
    mod->timeout_timer = NULL;

    char *buffer = mod->buffer;

    int skip = mod->ts_len_in_buf;
    int r = asc_socket_recv(mod->sock, buffer + skip, HTTP_BUFFER_SIZE - skip);
    if(r <= 0)
    {
        on_close(mod);
        return;
    }
    r += mod->ts_len_in_buf;// Imagine that we've received more (+ previous part)

    int response = 0;

    parse_match_t m[4];

    // parse response
    if(mod->ready_state == 0)
    {
        if(!http_parse_response(buffer, m))
        {
            call_error(mod, "invalid response");
            on_close(mod);
            return;
        }

        lua_newtable(lua);
        response = lua_gettop(lua);

        lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref);
        lua_pushvalue(lua, -2); // duplicate table
        lua_setfield(lua, -2, __response);
        lua_pop(lua, 1); // options

        lua_pushnumber(lua, atoi(&buffer[m[2].so]));
        lua_setfield(lua, response, __code);
        lua_pushlstring(lua, &buffer[m[3].so], m[3].eo - m[3].so);
        lua_setfield(lua, response, __message);

        skip = m[0].eo;
        mod->ready_state = 1;

        if(skip >= r)
        {
            lua_pop(lua, 1); // response
            return;
        }
    }

    // parse headers
    if(mod->ready_state == 1)
    {
        if(!response)
        {
            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref);
            lua_getfield(lua, -1, __response);
            lua_remove(lua, -2);
            response = lua_gettop(lua);
        }

        int headers_count = 0;
        lua_getfield(lua, response, __headers);
        if(lua_isnil(lua, -1))
        {
            lua_pop(lua, 1);
            lua_newtable(lua);
            lua_pushvalue(lua, -1);
            lua_setfield(lua, response, __headers);
        }
        else
        {
            headers_count = luaL_len(lua, -1);
        }
        const int headers = lua_gettop(lua);

        while(skip < r && http_parse_header(&buffer[skip], m))
        {
            const size_t so = m[1].so;
            const size_t length = m[1].eo - so;
            if(!length)
            {
                skip += m[0].eo;
                mod->ready_state = 2;
                break;
            }
            const char *header = &buffer[skip + so];

            if(!strncasecmp(header, __transfer_encoding, sizeof(__transfer_encoding) - 1))
            {
                const char *val = &header[sizeof(__transfer_encoding) - 1];
                if(!strncasecmp(val, __chunked, sizeof(__chunked) - 1))
                    mod->is_chunked = 1;
            }
            else if(!strncasecmp(header, __connection, sizeof(__connection) - 1))
            {
                const char *val = &header[sizeof(__connection) - 1];
                if(!strncasecmp(val, __close, sizeof(__close) - 1))
                    mod->is_close = 1;
                else if(!strncasecmp(val, __keep_alive, sizeof(__keep_alive) - 1))
                    mod->is_keep_alive = 1;
            }
            else if(!strncasecmp(header, __content_length, sizeof(__content_length) - 1))
            {
                const char *val = &header[sizeof(__content_length) - 1];
                mod->is_content_length = 1;
                mod->chunk_left = strtoul(val, NULL, 10);
            }

            ++headers_count;
            lua_pushnumber(lua, headers_count);
            lua_pushlstring(lua, header, length);
            lua_settable(lua, headers);
            skip += m[0].eo;
        }

        lua_pop(lua, 1); // headers

        if(mod->ready_state == 2)
        {
            get_lua_callback(mod);
            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
            lua_pushvalue(lua, response);
            lua_call(lua, 2, 0);

            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref);
            lua_pushnil(lua);
            lua_setfield(lua, -2, __response);
            lua_pop(lua, 1); // options
        }

        lua_pop(lua, 1); // response

        if(skip >= r)
            return;
    }

    // content
    if(mod->ready_state == 2)
    {
        /* Push to stream */
        if (mod->is_ts)
        {
            int pos = skip - mod->ts_len_in_buf;// buffer rewind
            while (r - pos >= TS_PACKET_SIZE)
            {
                module_stream_send(mod, (uint8_t*)&mod->buffer[pos]);
                pos += TS_PACKET_SIZE;
            }
            int left = r - pos;
            if (left > 0)
            {//there is something usefull in the end of buffer, move it to begin
                if (pos > 0) memmove(&mod->buffer[0], &mod->buffer[pos], left);
                mod->ts_len_in_buf = left;
            } else
            {//all data is processed
                mod->ts_len_in_buf = 0;
            }
        }

        // Transfer-Encoding: chunked
        else if(mod->is_chunked)
        {
            while(skip < r)
            {
                if(!mod->chunk_left)
                {
                    if(!http_parse_chunk(&buffer[skip], m))
                    {
                        call_error(mod, "invalid chunk");
                        on_close(mod);
                        return;
                    }

                    char cs_str[] = "00000000";
                    const size_t cs_size = m[1].eo - m[1].so;
                    const size_t cs_skip = 8 - cs_size;
                    memcpy(&cs_str[cs_skip], &buffer[skip], cs_size);

                    uint8_t cs_hex[4];
                    str_to_hex(cs_str, cs_hex, sizeof(cs_hex));
                    mod->chunk_left = (cs_hex[0] << 24)
                                    | (cs_hex[1] << 16)
                                    | (cs_hex[2] <<  8)
                                    | (cs_hex[3]      );
                    skip += m[0].eo;

                    if(!mod->chunk_left)
                    {
                        if(mod->is_keep_alive)
                        {
                            // keep-alive connection
                            get_lua_callback(mod);
                            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                            lua_pushstring(lua, "");
                            lua_call(lua, 2, 0);
                        }
                        else
                        {
                            // close connection
                            on_close(mod);
                        }
                        return;
                    }
                }

                const size_t r_skip = r - skip;
                get_lua_callback(mod);
                lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                if(mod->chunk_left < r_skip)
                {
                    lua_pushlstring(lua, &buffer[skip], mod->chunk_left);
                    lua_call(lua, 2, 0);
                    skip += mod->chunk_left;
                    mod->chunk_left = 0;
                    if(buffer[skip] == '\r')
                        ++skip;
                    if(buffer[skip] == '\n')
                        ++skip;
                    else
                    {
                        call_error(mod, "invalid chunk");
                        on_close(mod);
                        return;
                    }
                }
                else
                {
                    lua_pushlstring(lua, &buffer[skip], r_skip);
                    lua_call(lua, 2, 0);
                    mod->chunk_left -= r_skip;
                    break;
                }
            }
        }

        // Content-Length
        else if(mod->is_content_length)
        {
            if(mod->chunk_left > 0)
            {
                const size_t r_skip = r - skip;
                get_lua_callback(mod);
                lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                if(mod->chunk_left > r_skip)
                {
                    lua_pushlstring(lua, &buffer[skip], r_skip);
                    lua_call(lua, 2, 0);
                    mod->chunk_left -= r_skip;
                }
                else
                {
                    lua_pushlstring(lua, &buffer[skip], mod->chunk_left);
                    lua_call(lua, 2, 0);
                    mod->chunk_left = 0;

                    if(mod->is_keep_alive)
                    {
                        // keep-alive connection
                        get_lua_callback(mod);
                        lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                        lua_pushstring(lua, "");
                        lua_call(lua, 2, 0);
                    }
                    else
                    {
                        // close connection
                        on_close(mod);
                    }
                    return;
                }
            }
        }

        // Stream
        else
        {
            get_lua_callback(mod);
            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
            lua_pushlstring(lua, &buffer[skip], r - skip);
            lua_call(lua, 2, 0);
        }
    }
} /* on_read */
Exemplo n.º 7
0
// Processes a single request from a web client.
void webserver_process_request (int connfd, string clientaddress)
{
  mutex_requests.lock ();
  config_globals_simultaneous_connection_count++;
  mutex_requests.unlock ();

  // The environment for this request.
  // It gets passed around from function to function during the entire request.
  // This provides thread-safety to the request.
  Webserver_Request request;

  // Store remote client address in the request.
  request.remote_address = clientaddress;
  
  try {
    if (config_globals_running) {
      
      // Connection health flag.
      bool connection_healthy = true;
      
      // Read the client's request.
      // With the HTTP protocol it is not possible to read the request till EOF,
      // because EOF does never come, because the browser keeps the connection open
      // for the response.
      // The HTTP protocol works per line.
      // Read one line of data from the client.
      // An empty line marks the end of the headers.
#define BUFFERSIZE 2048
      int bytes_read;
      bool header_parsed = true;
      char buffer [BUFFERSIZE];
      // Fix valgrind unitialized value message.
      memset (&buffer, 0, BUFFERSIZE);
      do {
        bytes_read = get_line (connfd, buffer, BUFFERSIZE);
        if (bytes_read <= 0) connection_healthy = false;
        // Parse the browser's request's headers.
        header_parsed = http_parse_header (buffer, &request);
      } while (header_parsed);
      
      if (connection_healthy) {
        
        // In the case of a POST request, more data follows: The POST request itself.
        // The length of that data is indicated in the header's Content-Length line.
        // Read that data, and parse it.
        string postdata;
        if (request.is_post) {
          bool done_reading = false;
          int total_bytes_read = 0;
          do {
            bytes_read = read (connfd, buffer, BUFFERSIZE);
            for (int i = 0; i < bytes_read; i++) {
              postdata += buffer [i];
            }
            // EOF indicates reading is ready.
            // An error also indicates that reading is ready.
            if (bytes_read <= 0) done_reading = true;
            if (bytes_read < 0) connection_healthy = false;
            // "Content-Length" bytes read: Done.
            total_bytes_read += bytes_read;
            if (total_bytes_read >= request.content_length) done_reading = true;
          } while (!done_reading);
          if (total_bytes_read < request.content_length) connection_healthy = false;
        }
        
        if (connection_healthy) {

          http_parse_post (postdata, &request);
          
          // Assemble response.
          bootstrap_index (&request);
          http_assemble_response (&request);
          
          // Send response to browser.
          const char * output = request.reply.c_str();
          // The C function strlen () fails on null characters in the reply, so take string::size()
          size_t length = request.reply.size ();
          int written = write (connfd, output, length);
          if (written) {};
          
        } else {
          // cerr << "Insufficient data received, closing connection" << endl;
        }

      } else {
        // cerr << "Unhealthy connection was closed" << endl;
      }
    }
  } catch (exception & e) {
    string message ("Internal error: ");
    message.append (e.what ());
    Database_Logs::log (message);
  } catch (exception * e) {
    string message ("Internal error: ");
    message.append (e->what ());
    Database_Logs::log (message);
  } catch (...) {
    Database_Logs::log ("A general internal error occurred");
  }
  
  // Done: Close.
  close (connfd);

  mutex_requests.lock ();
  config_globals_simultaneous_connection_count--;
  mutex_requests.unlock ();
}
Exemplo n.º 8
0
/*
  called when a web connection becomes readable
*/
static void websrv_recv(struct stream_connection *conn, uint16_t flags)
{
	struct web_server_data *wdata;
	struct websrv_context *web = talloc_get_type(conn->private_data,
						     struct websrv_context);
	NTSTATUS status;
	uint8_t buf[1024];
	size_t nread;
	uint8_t *p;
	DATA_BLOB b;

	/* not the most efficient http parser ever, but good enough for us */
	status = socket_recv(conn->socket, buf, sizeof(buf), &nread);
	if (NT_STATUS_IS_ERR(status)) goto failed;
	if (!NT_STATUS_IS_OK(status)) return;

	if (!data_blob_append(web, &web->input.partial, buf, nread))
		goto failed;

	/* parse any lines that are available */
	b = web->input.partial;
	while (!web->input.end_of_headers &&
	       (p=(uint8_t *)memchr(b.data, '\n', b.length))) {
		const char *line = (const char *)b.data;
		*p = 0;
		if (p != b.data && p[-1] == '\r') {
			p[-1] = 0;
		}
		status = http_parse_header(web, line);
		if (!NT_STATUS_IS_OK(status)) return;
		b.length -= (p - b.data) + 1;
		b.data = p+1;
	}

	/* keep any remaining bytes in web->input.partial */
	if (b.length == 0) {
		b.data = NULL;
	}
	b = data_blob_talloc(web, b.data, b.length);
	data_blob_free(&web->input.partial);
	web->input.partial = b;

	/* we finish when we have both the full headers (terminated by
	   a blank line) and any post data, as indicated by the
	   content_length */
	if (web->input.end_of_headers &&
	    web->input.partial.length >= web->input.content_length) {
		if (web->input.partial.length > web->input.content_length) {
			web->input.partial.data[web->input.content_length] = 0;
		}
		EVENT_FD_NOT_READABLE(web->conn->event.fde);

		/* the reference/unlink code here is quite subtle. It
		 is needed because the rendering of the web-pages, and
		 in particular the esp/ejs backend, is semi-async.  So
		 we could well end up in the connection timeout code
		 while inside http_process_input(), but we must not
		 destroy the stack variables being used by that
		 rendering process when we handle the timeout. */
		if (!talloc_reference(web->task, web)) goto failed;
		wdata = talloc_get_type(web->task->private_data, struct web_server_data);
		if (wdata == NULL) goto failed;
		wdata->http_process_input(wdata, web);
		talloc_unlink(web->task, web);
	}
	return;

failed:
	stream_terminate_connection(conn, "websrv_recv: failed");
}
Exemplo n.º 9
0
	/* parsing lists {{{*/
	if(service)
	{
		xmlNodePtr memberships = findNode(service->children, "Memberships", 1);
		xmlNodePtr ms;
		xmlNodePtr role;
		xmlNodePtr members, member;
		xmlNodePtr pname;
		xmlNodePtr type;
		xmlNodePtr lastchange;
		xmlChar *content;
		int flag = 0;
		lastchange = findNode(service->children, "LastChange", 1);
		content = xmlNodeGetContent(lastchange);
		cl->lastchange = strdup((char*)content);
		DMSG(stderr, "Contact: lastchange = %s\n", cl->lastchange);
		if(!memberships)
		{
			fprintf(stderr, "NULL membership\n");
			count = 0;
			goto cleanup;
		}
		for(ms=memberships->children;ms;ms=ms->next)
		{
			int ctype = 1;
			if(!ms->children) continue;
			role = findNode(ms->children, "MemberRole", 1);
			if(!role)
			{
				fprintf(stderr, "Null role\n");
				count = 0;
				goto cleanup;
			}
			members = findNode(role, "Members", 1);
			if(!members) continue;

			if(xmlStrEqual(role->children->content, (xmlChar*)"Allow"))
				flag = 3;
			else if(xmlStrEqual(role->children->content, (xmlChar*)"Block"))
				flag = 4;
			else
				continue;

			for(member=members->children;member;member=member->next)
			{
				Contact *c;
				type = findNode(member->children, "Type", 1);
				content = xmlNodeGetContent(type);
				if(!content)
				{
					fprintf(stderr, "NULL Type\n");
					continue;
				}
				if(xmlStrEqual(content, (xmlChar*)"Passport"))
				{
					pname = findNode(member->children, "PassportName", 1);
					ctype = 1;
				}
				else if(xmlStrEqual(content, (xmlChar*)"Email"))
				{
					pname = findNode(member->children, "Email", 1);
					ctype = 32;
				}
				else
					continue;

				xmlFree(content);
				if(!pname) 
				{
					fprintf(stderr, "NULL PassportName or Email\n");
					continue;
				}
				content = xmlNodeGetContent(pname);
				if(content)
				{
					char name[32];
					char domain[32];
					if(sscanf((char*)content, "%[^@]@%s", name, domain) != 2)
					{
						fprintf(stderr, "parse contact: malformed email: %s\n", content);
						continue;
					}
					c = contact_new((char*)content);
					c->name = strdup(name);
					c->type = ctype;
					c->status = NA;
					c->inlist |= flag;
					c->domain = NULL; /* should be filled during sort */
					cl_append_contact(cl, c, name, domain);
					xmlFree(content);
					count++;
				}
			}
		}
	}/*}}}*/
	DMSG(stderr, "parsed contact count: %d\n", count);

cleanup:
	cl->flag &= ~CL_INITLIST;
	return count;

}/*}}}*/
int _cl_do_soapreq_ab(CL *cl)/*{{{*/
{
	TCPClient *client;
	char *req = NULL;
	char *header;
	char buf[512];
	int ret, len;
	char *ptr = NULL;
	client = tcpclient_new("contacts.msn.com", 80);
	ret = _cl_load_soapreq_ab(cl, cl->ablastchange, &req, TRUE);
	if(ret)
	{
		tcpclient_connect(client);
		header = (char*)xmalloc(strlen(ab_request_header) + 32);
		DMSG(stderr, "sending ab request\n");
		len = sprintf(header, "%s%d\r\n\r\n", ab_request_header, ret);
		if(tcpclient_send(client, header, len) <= 0) goto cleanup;
		if(tcpclient_send(client, req, ret) <= 0) goto cleanup;

		len = tcpclient_recv_header(client, &ptr); /* header */
		if(ptr)
		{
			HTTPHeader *header;
			xmlDocPtr doc;
			xmlParserCtxtPtr ctxt;
			FILE *fp;

			DMSG(stderr, "AB response header:\n%s", ptr);
			header = http_parse_header(ptr);
			len = header->content_length;
			DMSG(stderr, "Length: %d\n", len);
			http_header_destroy(header);
			memset(buf, 0, sizeof(buf));
			fp = fopen("addressbook.xml", "w");
			fprintf(fp, buf);
			len -= (ret = tcpclient_recv(client, buf, sizeof(buf)-1));
			ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, ret, "addressbook.xml");
			fprintf(fp, buf);
			if(ctxt == NULL)
			{
				fprintf(stderr, "failed to create parser context");
				return 0;
			}

			while(len > 0)
			{
				memset(buf, 0, sizeof(buf));
				len -= (ret=tcpclient_recv(client, buf, sizeof(buf)-1));
				fprintf(fp, buf);
				xmlParseChunk(ctxt, buf, ret, 0);
			}
			fclose(fp);
			xmlParseChunk(ctxt, buf, 0, 1);
			tcpclient_destroy(client);
			client = NULL;
			doc = ctxt->myDoc;
			len = ctxt->wellFormed;
			xmlFreeParserCtxt(ctxt);
			//count += _cl_parse_contacts(cl, doc);
			xmlFreeDoc(doc);
			xmlCleanupParser();
			DMSG(stderr, "addressbook xml parsing done: %s\n", len?"good":"malformed");
			xfree(ptr);
		}
		else
		{
			DMSG(stderr, "ab: no header found\n\r");
		}
	}
	else
	{
		fprintf(stderr, "failed to load abreq\n");
	}
cleanup:
	xfree(header);
	return 0;
}/*}}}*/
int cl_load_contacts(CL *cl, const char* file)/*{{{*/
{
	int ret;
	xmlDocPtr doc;
	xmlNodePtr root;
	xmlNodePtr contact;
	xmlNodePtr node;
	xmlChar *content;

	doc = xmlReadFile(file, NULL, 0);
	if (doc == NULL)
	{
		fprintf(stderr, "Failed to parse %s\n", file);
		return 0;
	}
	ret = 0;
	root = xmlDocGetRootElement(doc);
	contact = findNode(root->children, "contact", 3);
#define READSTR(dst,elem)  node = findNode(contact->children, elem, 1); \
	content = xmlNodeGetContent(node); \
	dst = strdup((char*)content); \
	xmlFree(content)

#define READINT(dst, elem) node = findNode(contact->children, elem, 1); \
		content = xmlNodeGetContent(node); \
		dst = atoi((char*)content); \
		xmlFree(content)
	for(;contact;contact=contact->next)
	{
		Contact *c;
		node = findNode(contact->children, "nick", 1);
		content = xmlNodeGetContent(node);
		c = contact_new((char*)content);
		xmlFree(content);
		READSTR(c->name, "name");
		READSTR(c->PSM, "PSM");
		READINT(c->inlist, "inlist");
		READINT(c->type, "type");
		c->status = NA;

		node = findNode(contact->children, "domain", 1);
		content = xmlNodeGetContent(node);
		c->domain = NULL; /* should be filled during sort */
		cl_append_contact(cl, c, c->name, (char*)content);
		xmlFree(content);
		ret++;
	}
	node = findNode(root->children, "lastchange", 3);
	if(node)
	{
		content = xmlNodeGetContent(node);
		cl->lastchange = strdup((char*)content);
		xmlFree(content);
	}
	xmlFreeDoc(doc);
	return ret;
}/*}}}*/
void cl_save(CL *cl, const char *filename)/*{{{*/
{
	Contact *c;
	FILE *fp = fopen(filename, "w");
	if(!fp) return;
	fprintf(fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>");
	fprintf(fp, "<contactinfo>");
	fprintf(fp, "<contacts>");
	for(c=cl->list;c;c=c->g_next)
	{
		fprintf(fp, "<contact>");
		fprintf(fp, "<name>%s</name>", c->name);
		fprintf(fp, "<nick>%s</nick>", c->nick);
		fprintf(fp, "<PSM>%s</PSM>", c->PSM?c->PSM:"");
		fprintf(fp, "<domain>%s</domain>", c->domain);
		fprintf(fp, "<inlist>%d</inlist>", c->inlist);
		fprintf(fp, "<type>%d</type>", c->type);
		fprintf(fp, "</contact>");
	}
	fprintf(fp, "</contacts>");
	if(cl->lastchange)
		fprintf(fp,"<lastchange>%s</lastchange>", cl->lastchange);
	if(cl->ablastchange)
		fprintf(fp,"<ablastchange>%s</ablastchange>", cl->ablastchange);
	fprintf(fp, "</contactinfo>");
	fflush(fp);
	fclose(fp);
}/*}}}*/
int _cl_do_soapreq_ms(CL *cl)/*{{{*/
{
	SSLClient *client;
	int ret;
	int len;
	int count = 0;
	char *req = NULL;
	char *header;
	char contactfile[64];
	FILE *fp;

	header = (char*)xmalloc(strlen(ms_request_header) + 32);

	client = sslclient_new(DEFAULTSERVER, 443);
	if(!sslclient_connect(client))
		return 0;
	/* connected */
	
	MD5((unsigned char*)cl->account->username, strlen(cl->account->username), (unsigned char*)contactfile);
	sprintf(contactfile, "%x%x.xml", (unsigned char)contactfile[0], (unsigned char)contactfile[1]);
	if((fp=fopen(contactfile, "r")))
	{
		DMSG(stderr, "loading cached contacts...\n");
		if((count = cl_load_contacts(cl, contactfile)))
			ret = _cl_load_soapreq_ms(cl, cl->lastchange, &req, FALSE);
		else
			ret = _cl_load_soapreq_ms(cl, cl->lastchange, &req, TRUE);
		DMSG(stderr, "%d contacts loaded from cache...\n", count);

		fclose(fp);
	}
	else
		ret = _cl_load_soapreq_ms(cl, cl->lastchange, &req, TRUE);
	if(ret)
	{
		char buf[512] = {0};
		char *ptr = NULL;
		xmlDocPtr doc;
		xmlParserCtxtPtr ctxt;
		FILE *fp;

		DMSG(stderr, "sending cl request\n");
		/* send request */
		len = sprintf(header, ms_request_header, ret);
		if(sslclient_send(client, header, len) <= 0) goto cleanup;
		if(sslclient_send(client, req, ret) <= 0) goto cleanup;

		DMSG(stderr, "getting cl response\n");
		/* get response */
		DMSG(stderr, "HEADER:\n");
		len = sslclient_recv_header(client, &ptr); /* header */
		if(ptr)
		{
			HTTPHeader *header;
			DMSG(stderr, ptr);
			header = http_parse_header(ptr);
			len = header->content_length;
			DMSG(stderr, "content length: %d\n", len);
			http_header_destroy(header);
			xfree(ptr);
		}
		else
		{
			DMSG(stderr, "no header found\n\r");
		}

		memset(buf, 0, sizeof(buf));

		fp = fopen("contacts.xml", "w");
		len -= (ret = sslclient_recv(client, buf, sizeof(buf)-1));
		ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, ret, "contacts.xml");
		DMSG(stderr, "RESPONSE:\n");
		fprintf(fp, buf);
		if(ctxt == NULL)
		{
			fprintf(stderr, "failed to create parser context");
			return 0;
		}

		while(len > 0)
		{
			memset(buf, 0, sizeof(buf));
			len -= (ret=sslclient_recv(client, buf, sizeof(buf)-1));
			fprintf(fp, buf);
			xmlParseChunk(ctxt, buf, ret, 0);
		}
		fclose(fp);
		xmlParseChunk(ctxt, buf, 0, 1);
		sslclient_destroy(client, FALSE);
		client = NULL;
		doc = ctxt->myDoc;
		len = ctxt->wellFormed;
		xmlFreeParserCtxt(ctxt);
		count += _cl_parse_contacts(cl, doc);
		xmlFreeDoc(doc);
		xmlCleanupParser();
		DMSG(stderr, "contact xml parsing done: %s\n", len?"good":"malformed");
	}
	_cl_sort_contacts(cl);
	cl_save(cl, contactfile);
cleanup:
	xfree(req);
	xfree(header);
	return count;
}/*}}}*/
Exemplo n.º 10
0
	/* parsing lists {{{*/
	if(service)
	{
		xmlNodePtr memberships = findNode(service->children, "Memberships", 1);
		xmlNodePtr ms;
		xmlNodePtr role;
		xmlNodePtr members, member;
		xmlNodePtr pname;
		xmlNodePtr type;
		xmlNodePtr lastchange;
		xmlChar *content;
		int flag = 0;
		lastchange = findNode(service->children, "LastChange", 1);
		content = xmlNodeGetContent(lastchange);
		cl->lastchange = strdup((char*)content);
		DMSG(stderr, "Contact: lastchange = %s\n", cl->lastchange);
		if(!memberships)
		{
			fprintf(stderr, "NULL membership\n");
			count = 0;
			goto cleanup;
		}
		for(ms=memberships->children;ms;ms=ms->next)
		{
			int ctype = 1;
			if(!ms->children) continue;
			role = findNode(ms->children, "MemberRole", 1);
			if(!role)
			{
				fprintf(stderr, "Null role\n");
				count = 0;
				goto cleanup;
			}
			members = findNode(role, "Members", 1);
			if(!members) continue;

			if(xmlStrEqual(role->children->content, (xmlChar*)"Allow"))
				flag = 3;
			else if(xmlStrEqual(role->children->content, (xmlChar*)"Block"))
				flag = 4;
			else
				continue;

			for(member=members->children;member;member=member->next)
			{
				Contact *c;
				type = findNode(member->children, "Type", 1);
				content = xmlNodeGetContent(type);
				if(!content)
				{
					fprintf(stderr, "NULL Type\n");
					continue;
				}
				if(xmlStrEqual(content, (xmlChar*)"Passport"))
				{
					pname = findNode(member->children, "PassportName", 1);
					ctype = 1;
				}
				else if(xmlStrEqual(content, (xmlChar*)"Email"))
				{
					pname = findNode(member->children, "Email", 1);
					ctype = 32;
				}
				else
					continue;

				xmlFree(content);
				if(!pname) 
				{
					fprintf(stderr, "NULL PassportName or Email\n");
					continue;
				}
				content = xmlNodeGetContent(pname);
				if(content)
				{
					char name[32];
					char domain[32];
					if(sscanf((char*)content, "%[^@]@%s", name, domain) != 2)
					{
						fprintf(stderr, "parse contact: malformed email: %s\n", content);
						continue;
					}
					c = contact_new((char*)content);
					c->name = strdup(name);
					c->type = ctype;
					c->status = NA;
					c->inlist |= flag;
					c->domain = NULL; /* should be filled during sort */
					cl_append_contact(cl, c, name, domain);
					xmlFree(content);
					count++;
				}
			}
		}
	}/*}}}*/
	DMSG(stderr, "parsed contact count: %d\n", count);

cleanup:
	cl->flag &= ~CL_INITLIST;
	return count;

}/*}}}*/
int _cl_do_soapreq_ab(CL *cl)/*{{{*/
{
	TCPClient *client;
	char *req = NULL;
	char *header;
	char buf[512];
	int ret, len;
	char *ptr = NULL;
	client = tcpclient_new("contacts.msn.com", 80);
	ret = _cl_load_soapreq_ab(cl, cl->ablastchange, &req, TRUE);
	if(ret)
	{
		tcpclient_connect(client);
		header = (char*)xmalloc(strlen(ab_request_header) + 32);
		DMSG(stderr, "sending ab request\n");
		len = sprintf(header, "%s%d\r\n\r\n", ab_request_header, ret);
		if(tcpclient_send(client, header, len) <= 0) goto cleanup;
		if(tcpclient_send(client, req, ret) <= 0) goto cleanup;

		len = tcpclient_recv_header(client, &ptr); /* header */
		if(ptr)
		{
			HTTPHeader *header;
			xmlDocPtr doc;
			xmlParserCtxtPtr ctxt;
			FILE *fp;

			DMSG(stderr, "AB response header:\n%s", ptr);
			header = http_parse_header(ptr);
			len = header->content_length;
			DMSG(stderr, "Length: %d\n", len);
			http_header_destroy(header);
			memset(buf, 0, sizeof(buf));
			fp = fopen("addressbook.xml", "w");
			fprintf(fp, buf);
			len -= (ret = tcpclient_recv(client, buf, sizeof(buf)-1));
			ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, ret, "addressbook.xml");
			fprintf(fp, buf);
			if(ctxt == NULL)
			{
				fprintf(stderr, "failed to create parser context");
				return 0;
			}

			while(len > 0)
			{
				memset(buf, 0, sizeof(buf));
				len -= (ret=tcpclient_recv(client, buf, sizeof(buf)-1));
				fprintf(fp, buf);
				xmlParseChunk(ctxt, buf, ret, 0);
			}
			fclose(fp);
			xmlParseChunk(ctxt, buf, 0, 1);
			tcpclient_destroy(client);
			client = NULL;
			doc = ctxt->myDoc;
			len = ctxt->wellFormed;
			xmlFreeParserCtxt(ctxt);
			//count += _cl_parse_contacts(cl, doc);
			xmlFreeDoc(doc);
			xmlCleanupParser();
			DMSG(stderr, "addressbook xml parsing done: %s\n", len?"good":"malformed");
			xfree(ptr);
		}
		else
		{
			DMSG(stderr, "ab: no header found\n\r");
		}
	}
	else
	{
		fprintf(stderr, "failed to load abreq\n");
	}
cleanup:
	xfree(header);
	return 0;
}/*}}}*/
Exemplo n.º 11
0
guint http_request_read (http_request *h) {
    gchar *buf = g_new( gchar, BUFSIZ + 1 );
/*
    GIOStatus r;
    GError *err = NULL;
*/
    GIOError r;
    guint s, times, n = 0, t = 0;
    gchar *c_len_hdr = NULL;
    guint hdr_len = 0, c_len = 0, tot_req_size = 0;
    struct timeval tv;
    fd_set fdset;

    FD_ZERO(&fdset);
    FD_SET(g_io_channel_unix_get_fd(h->sock), &fdset);
    tv.tv_sec = 0;
    buf[0] = '\0';
    buf[BUFSIZ] = '\0';

    //    for (t = 0, n = BUF_SIZ; n == BUF_SIZ &&
    //      h->buffer->len < MAX_REQUEST_SIZE; t += n ) {
    // BPsmythe: The above (original) loop will never execute
    // more than once unless the size of the buffer read in (n)
    // is equal to the constant BUF_SIZE.  What is desired is
    // to keep looping until there is nothing left to read.
    // The for was changed to look for the end of the headers.
    // FIXME: We should use the newer g_io_channel_read_char
    //
    // TJaqua: Added buffer overflow checking, content read loop from 0.93pre2, and fixed up the timeouts, logging and error exits

    if (CONFd("Verbosity") >= 7) g_message("http_request_read: READING request from peer %s (on %s, fd: %d)", h->peer_ip, h->sock_ip, g_io_channel_unix_get_fd(h->sock));
    if (CONFd("Verbosity") >= 9) g_message("http_request_read: entering HEADER read loop (BUFSIZE=%u)", BUFSIZ);
    for (times=MAX_REQ_TIMEOUTS; !hdr_len && (times > 0); t += n ) {
	n=0;
/*
	r = g_io_channel_read_chars( h->sock, buf, BUFSIZ, &n, &err );
	if (r == G_IO_STATUS_ERROR || err != NULL) {
	    g_message( "http_request_read: Socket IO ERROR: %s, exiting!", err->message );
	    g_error_free(err);
*/
	r = g_io_channel_read( h->sock, buf, BUFSIZ, &n);
	if (r != G_IO_ERROR_NONE) {
	    g_warning( "http_request_read: Socket IO ERROR: %m, exiting!" );
	    g_free(buf);
	    return 0;
	}

	if (CONFd("Verbosity") >= 9) g_message("http_request_read: HEADER loop read %u bytes", n);
	buf[n] = '\0';
	if (n && CONFd("Verbosity") >= 11) syslog_message("RAW_HDR_BUF: ", buf, n);

	if(strlen(buf) < n-1) g_warning("http_request_read: Trailing data past string in buffer was DICARDED!");
	if (h->buffer->len == MAX_REQUEST_SIZE)
	    g_warning("http_request_read: header buffer full (%u bytes, %u bytes discarded!)", MAX_REQUEST_SIZE, n);
	else if (n <= (MAX_REQUEST_SIZE - h->buffer->len)) {
	    if(CONFd("Verbosity") >= 11) g_message("http_request_read: APPENDING buffer to HEADER.");
	    if(n) g_string_append(h->buffer, buf);
	    else if (CONFd("Verbosity") >= 6) g_message("http_request_read: No data in buffer.");
	    //if(CONFd("Verbosity") >= 11) g_message("http_request_read: Partial HEADER (%u bytes) is: %s", h->buffer->len, h->buffer->str);
	}
	else {
	    if(CONFd("Verbosity") >= 6) g_warning("http_request_read: header buffer full (%u bytes, %u bytes discarded!)", 
                                                  MAX_REQUEST_SIZE, n - (MAX_REQUEST_SIZE - h->buffer->len));
	    buf[MAX_REQUEST_SIZE - h->buffer->len] = '\0';
	    g_string_append(h->buffer, buf);
	}
        times--;

        // BPsmythe: Check for the end of the headers.
	if (hdr_len = http_get_hdr_len(h->buffer->str)) {
	        if (CONFd("Verbosity") >= 6) g_message("http_request_read: HEADER END found, length: %u", hdr_len );
        }
	else {
	    if(!times) { 
                if(CONFd("Verbosity") >= 6) {
                    g_message("http_request_read: ERROR: HEADER END not found after %d tries, exiting!", MAX_REQ_TIMEOUTS);
	            if (!t) g_message("http_request_read: Empty HTTP-request header.");
	            else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n);
	        }
		//Should I send a FIN packet to shutdown the socket?
                g_free(buf);
	        return 0;
            }
	    if(CONFd("Verbosity") >= 11) g_message("http_request_read: Waiting for next I/O on socket, (%d more tries).", times);
            tv.tv_usec = REQ_TIMEOUT;
	    while(times && !(s = select (g_io_channel_unix_get_fd(h->sock)+1, &fdset, NULL, NULL, &tv))) {
                times--;
	        if (CONFd("Verbosity") >= 7)  g_message("http_request_read: HEADER select timeout, %d more tries", times);
                tv.tv_usec = REQ_TIMEOUT;
            }
	    if(s<0) {
	        g_warning("http_request_read: ERROR in select, exiting!");
		g_free(buf);
		return 0;
	    }
	    else if(!times) { 
                if(CONFd("Verbosity") >= 6) {
                    g_message("http_request_read: ERROR: Too many TIMEOUTS waiting for HEADER end!");
	            if (!t) g_message("http_request_read: Empty HTTP-request header.");
	            else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n);
	        }
		//Should I send a FIN packet to shutdown the socket?
                g_free(buf);
	        return 0;
            }
            else if(CONFd("Verbosity") >= 11) g_message("http_request_read: Recieved I/O on socket.");
	}
    }

    if (CONFd("Verbosity") >= 10) syslog_message("RAW_HEADER: ", h->buffer->str, h->buffer->len);
    
    // Read the content length from the header
    http_parse_header( h, h->buffer->str );

    if( (HEADER("Content-length")) && (c_len = atoi(HEADER("Content-length"))) ) {
        if (CONFd("Verbosity") >= 9) g_message("http_request_read: entering CONTENT read loop to read %u bytes.", c_len);
        tot_req_size = hdr_len + c_len;
        for (times=MAX_REQ_TIMEOUTS; (t < tot_req_size) && (times > 0); t += n ) {
	    if (CONFd("Verbosity") >= 9) g_message("http_request_read: %u bytes of %u total.", t, tot_req_size );
	    n=0;
/*
	    r = g_io_channel_read_chars( h->sock, buf, BUFSIZ, &n, &err );
	    if (r == G_IO_STATUS_ERROR || err != NULL) {
	        g_message( "http_request_read: Socket-IO ERROR: %s, exiting!", err->message );
	        g_error_free(err);
*/
	    r = g_io_channel_read( h->sock, buf, BUFSIZ, &n);
	    if (r != G_IO_ERROR_NONE) {
	        g_warning( "http_request_read: Socket-IO ERROR: %m, exiting!" );
	        g_free(buf);
	        return 0;
	    }

	    if (CONFd("Verbosity") >= 9) g_message("http_request_read: CONTENT loop read %d bytes", n );
	    buf[n] = '\0';
	    if (n && CONFd("Verbosity") >= 11) syslog_message("RAW_CON_BUF: ", buf, n); 

	    if (h->buffer->len == MAX_REQUEST_SIZE) {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Maximum request length EXCEEDED (%u bytes discarded! Continuing to read out content.)", n);
            }
	    else if (h->buffer->len == tot_req_size) {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Content length EXCEEDED (%u bytes discarded! Shouldn't happen!)", n);
            }
            else if (h->buffer->len + n >= MAX_REQUEST_SIZE) {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Max buffer length EXCEEDED (%u bytes discarded! Continuing to read out content.)", 
                                                       n - (MAX_REQUEST_SIZE - h->buffer->len));
                buf[MAX_REQUEST_SIZE - h->buffer->len] = '\0';
	        g_string_append(h->buffer, buf);
            }
	    else if (n <= (tot_req_size - h->buffer->len)) {
	        if(CONFd("Verbosity") >= 11) g_message("http_request_read: APPENDING buffer to CONTENT.");
	        if(n) g_string_append(h->buffer, buf);
	        else if (CONFd("Verbosity") >= 6) g_message("http_request_read: No data in buffer.");
	    }
	    else {
	        if(CONFd("Verbosity") >= 6) g_warning("http_request_read: Content length EXCEEDED (%u bytes added, %u bytes discarded!)", 
                                                       tot_req_size - h->buffer->len, n - (tot_req_size - h->buffer->len));
	        buf[tot_req_size - h->buffer->len] = '\0';
	        g_string_append(h->buffer, buf);
	    }
            times--;

            // TJaqua: Check for the end of the content.
	    if ((t+n) >= tot_req_size) {
                if (CONFd("Verbosity") >= 6) g_message("http_request_read: CONTENT end reached, length: %u", tot_req_size);
            }
	    else {
                if (!times) {
                    if(CONFd("Verbosity") >= 6) {
                        g_message("http_request_read: ERROR: CONTENT END not found after %d tries, exiting!", MAX_REQ_TIMEOUTS);
	                if (t == hdr_len) g_message("http_request_read: Empty CONTENT, socket may have stalled.");
	                else g_message("http_request_read: CONTENT unfinished, %u bytes read.", t+n);
	            }
                    //Should I send a FIN packet to shutdown the socket?
                    g_free(buf);
                    //We still got the header, though, so return it.
                    g_string_truncate(h->buffer, hdr_len);
	            return hdr_len;
                }
	        if(CONFd("Verbosity") >= 11) g_message("http_request_read: Waiting for next I/O on socket.");
                tv.tv_usec = REQ_TIMEOUT;
	        while (times && !(s = select (g_io_channel_unix_get_fd(h->sock)+1, &fdset, NULL, NULL, &tv))) {
                    times--;
	            if (CONFd("Verbosity") >= 7)  g_message("http_request_read: CONTENT select timeout, %d more tries", times);
                    tv.tv_usec = REQ_TIMEOUT;
                }
	        if(s<0) {
	            g_warning("http_request_read: ERROR in select, exiting!");
		    g_free(buf);
                    //We still got the header, though, so return it.
                    g_string_truncate(h->buffer, hdr_len);
	            return hdr_len;
	        }
                else if (!times) {
                    if(CONFd("Verbosity") >= 6) {
                        g_message("http_request_read: ERROR: Too many TIMEOUTS waiting for CONTENT end!");
	                if (t == hdr_len) g_message("http_request_read: Empty CONTENT, socket may have stalled.");
	                else g_message("http_request_read: Invalid HTTP-request header, %u bytes read.", t+n);
	            }
                    //Should I send a FIN packet to shutdown the socket?
                    g_free(buf);
                    //We still got the header, though, so return it.
                    g_string_truncate(h->buffer, hdr_len);
	            return hdr_len;
                }
                else if (CONFd("Verbosity") >= 11) g_message("http_request_read: Received I/O on socket.");
	    }
        }
        if (CONFd("Verbosity") >= 10) syslog_message("RAW_CONTENT: ", &(h->buffer->str[hdr_len]), h->buffer->len - hdr_len); 
        if (t<tot_req_size) 
	    g_message("http_request_read: CONTENT unfinished - should not happen!");
    }

    if (CONFd("Verbosity") >= 6) g_message("http_request_read: FINISHED read (%u bytes total), exiting.", t);
    g_free(buf);
    return t;
}