Beispiel #1
0
xmlNodePtr
soap_env_get_header(SoapEnv *env)
{
  xmlNodePtr node;

  if (!env)
  {
    log_error1("SoapEnv is NULL");
    return NULL;
  }

  if (!env->root)
  {
    log_error1("SoapEnv contains no document");
    return NULL;
  }

  for (node = soap_xml_get_children(env->root); node; node = soap_xml_get_next(node))
  {
    if (!xmlStrcmp(node->name, BAD_CAST "Header")
     && !xmlStrcmp(node->ns->href, BAD_CAST soap_env_ns))
      return node;
  }

  return NULL;
}
Beispiel #2
0
char *
soap_env_find_methodname(SoapEnv * env)
{
  xmlNodePtr body, node;

  body = soap_env_get_body(env);
  if (body == NULL)
    return 0;

  node = soap_xml_get_children(body);   /* node is the first child */

  if (node == NULL)
  {
    log_error1("No method found");
    return 0;
  }

  if (node->name == NULL)
  {
    log_error1("No methodname found");
    return 0;

  }

  return((char *) node->name);
}
Beispiel #3
0
xmlNodePtr
soap_env_get_body(SoapEnv * env)
{
  xmlNodePtr node;

  if (env == NULL)
  {
    log_error1("env object is NULL");
    return NULL;
  }

  if (env->root == NULL)
  {
    log_error1("env has no xml");
    return NULL;
  }

  for (node = soap_xml_get_children(env->root); node; node = soap_xml_get_next(node))
  {
    if (!xmlStrcmp(node->name, BAD_CAST "Body")
     && !xmlStrcmp(node->ns->href, BAD_CAST soap_env_ns))
      return node;
  }

  log_error1("Body tag not found!");
  return NULL;
}
Beispiel #4
0
/* XXX: unused function? */
xmlNodePtr
_soap_env_get_body(SoapEnv * env)
{
  xmlNodePtr body;
  xmlNodeSetPtr nodeset;
  xmlXPathObjectPtr xpathobj;

  if (env == NULL)
  {
    log_error1("SoapEnv is NULL");
    return NULL;
  }

  if (env->root == NULL)
  {
    log_error1("SoapEnv contains no XML document");
    return NULL;
  }

  /* 
     find <Body> tag find out namespace xpath: //Envelope/Body/ */
  xpathobj = soap_xpath_eval(env->root->doc, "//Envelope/Body");

  if (!xpathobj)
  {
    log_error1("No Body (xpathobj)!");
    return NULL;
  }

  if (!(nodeset = xpathobj->nodesetval))
  {
    log_error1("No Body (nodeset)!");
    xmlXPathFreeObject(xpathobj);
    return NULL;
  }

  if (nodeset->nodeNr < 1)
  {
    log_error1("No Body (nodeNr)!");
    xmlXPathFreeObject(xpathobj);
    return NULL;
  }

  body = nodeset->nodeTab[0];   /* body is <Body> */
  xmlXPathFreeObject(xpathobj);
  return body;

}
Beispiel #5
0
static herror_t
_hssl_server_context_init(void)
{
  log_verbose3("enabled=%i, certificate=%p", enabled, certificate);

  if (!enabled || !certificate)
    return H_OK;

  if (!(context = SSL_CTX_new(SSLv23_method())))
  {
    log_error1("Cannot create SSL context");
    return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT,
                      "Unable to create SSL context");
  }

  if (!(SSL_CTX_use_certificate_file(context, certificate, SSL_FILETYPE_PEM)))
  {
    log_error2("Cannot read certificate file: \"%s\"", certificate);
    SSL_CTX_free(context);
    return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE,
                      "Unable to use SSL certificate \"%s\"", certificate);
  }

  SSL_CTX_set_default_passwd_cb(context, _hssl_password_callback);

  if (!(SSL_CTX_use_PrivateKey_file(context, certificate, SSL_FILETYPE_PEM)))
  {
    log_error2("Cannot read key file: \"%s\"", certificate);
    SSL_CTX_free(context);
    return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM,
                      "Unable to use private key");
  }

  if (ca_list != NULL && *ca_list != '\0')
  {
    if (!(SSL_CTX_load_verify_locations(context, ca_list, NULL)))
    {
      SSL_CTX_free(context);
      log_error2("Cannot read CA list: \"%s\"", ca_list);
      return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST,
                        "Unable to read certification authorities \"%s\"");
    }

    SSL_CTX_set_client_CA_list(context, SSL_load_client_CA_file(ca_list));
    log_verbose1("Certification authority contacted");
  }

  SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
                     _hssl_cert_verify_callback);
  log_verbose1("Certificate verification callback registered");

  SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY);

  SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);

  _hssl_superseed();

  return H_OK;
}
Beispiel #6
0
herror_t
soap_env_new_from_doc(xmlDocPtr doc, SoapEnv ** out)
{
  xmlNodePtr node;
  SoapEnv *env;

  if (doc == NULL)
  {
    log_error1("Can not create xml document!");
    return herror_new("soap_env_new_from_doc",
                      GENERAL_INVALID_PARAM,
                      "XML Document (xmlDocPtr) is NULL");
  }

  if (!(node = xmlDocGetRootElement(doc)))
  {
    log_error1("XML document is empty!");
    return herror_new("soap_env_new_from_doc",
                      XML_ERROR_EMPTY_DOCUMENT, "XML Document is empty!");
  }

  if (!(env = (SoapEnv *) malloc(sizeof(SoapEnv))))
  {
    log_error2("malloc failed (%s)", strerror(errno));
    return herror_new("soap_env_from_doc", GENERAL_INVALID_PARAM, "malloc failed");
  }

 
  env->root = node;
  env->header = soap_env_get_header(env);
  env->body = soap_env_get_body(env);
  env->cur = soap_env_get_method(env);

  
  *out = env;

  return H_OK;
}
Beispiel #7
0
herror_t
hssl_server_ssl(hsocket_t * sock)
{
  SSL *ssl;
  int ret;
  BIO *sbio;

  if (!enabled)
    return H_OK;

  log_verbose2("Starting SSL initialization for socket %d", sock->sock);

  if (!(ssl = SSL_new(context)))
  {
    log_warn1("SSL_new failed");
    return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER,
                      "Cannot create SSL object");
  }
  /* SSL_set_fd(ssl, sock->sock); */

  sbio = BIO_new_socket(sock->sock, BIO_NOCLOSE);

  if (sbio == NULL)
  {
    log_error1("BIO_new_socket failed");
    return NULL;
  }
  // BIO_set_callback(sbio, hssl_bio_cb);
  sbio->method->bread = _hssl_bio_read;
  SSL_set_bio(ssl, sbio, sbio);


  if ((ret = SSL_accept(ssl)) <= 0)
  {
    herror_t err;

    log_error2("SSL_accept failed (%s)", _hssl_get_error(ssl, ret));

    err =
      herror_new("hssl_server_ssl", HSSL_ERROR_SERVER,
                 "SSL_accept failed (%s)", _hssl_get_error(ssl, ret));
    SSL_free(ssl);

    return err;
  }

  sock->ssl = ssl;

  return H_OK;
}
Beispiel #8
0
xmlNodePtr
soap_env_add_item(SoapEnv * call, const char *type, const char *name, const char *value)
{
  xmlNodePtr newnode;

  newnode = xmlNewTextChild(call->cur, NULL, BAD_CAST name, BAD_CAST value);

  if (newnode == NULL)
  {
    log_error1("Can not create new xml node");
    return NULL;
  }

  if (type)
  {
    if (!xmlNewProp(newnode, BAD_CAST "xsi:type", BAD_CAST type))
    {
      log_error1("Can not create new xml attribute");
      return NULL;
    }
  }
  return newnode;
}
static void
hurl_dump(const hurl_t * url)
{

  if (url == NULL)
  {
    log_error1("url is NULL!");
    return;
  }
  log_verbose2("PROTOCOL : %d", url->protocol);
  log_verbose2("    HOST : %s", url->host);
  log_verbose2("    PORT : %d", url->port);
  log_verbose2(" CONTEXT : %s", url->context);
}
Beispiel #10
0
xmlNodePtr
soap_env_add_attachment(SoapEnv * call, const char *name, const char *href)
{
  xmlNodePtr newnode;

  newnode = xmlNewTextChild(call->cur, NULL, BAD_CAST name, BAD_CAST "");

  if (newnode == NULL)
  {
    log_error1("Can not create new xml node");
    return NULL;
  }

  if (href)
  {
    if (!xmlNewProp(newnode, BAD_CAST "href", BAD_CAST href))
    {
      log_error1("Can not create new xml attribute");
      return NULL;
    }
  }

  return newnode;
}
Beispiel #11
0
herror_t
hssl_client_ssl(hsocket_t * sock)
{
  SSL *ssl;
  int ret;

  log_verbose1("Starting SSL client initialization");

  if (!(ssl = SSL_new(context)))
  {
    log_error1("Cannot create new SSL object");
    return herror_new("hssl_client_ssl", HSSL_ERROR_CLIENT, "SSL_new failed");
  }

  SSL_set_fd(ssl, sock->sock);

  if ((ret = SSL_connect(ssl)) <= 0)
  {
    herror_t err;

    log_error2("SSL connect error (%s)", _hssl_get_error(ssl, -1));
    err =
      herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT,
                 "SSL_connect failed (%s)", _hssl_get_error(ssl, ret));
    SSL_free(ssl);
    return err;
  }

  /* SSL_connect should take care of this for us. if
     (SSL_get_peer_certificate(ssl) == NULL) { log_error1("No certificate
     provided"); SSL_free(ssl); return herror_new("hssl_client_ssl",
     HSSL_ERROR_CERTIFICATE, "No certificate provided"); }

     if (SSL_get_verify_result(ssl) != X509_V_OK) { log_error1("Certificate
     did not verify"); SSL_free(ssl); return herror_new("hssl_client_ssl",
     HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); } */

  log_verbose1("SSL client initialization completed");

  sock->ssl = ssl;

  return H_OK;
}
char *
hpairnode_get(hpair_t * pair, const char *key)
{
  if (key == NULL)
  {
    log_error1("key is NULL");
    return NULL;
  }
  while (pair != NULL)
  {
    if (pair->key != NULL)
    {
      if (!strcmp(pair->key, key))
      {
        return pair->value;
      }
    }
    pair = pair->next;
  }

  return NULL;
}
Beispiel #13
0
char *
soap_env_find_urn(SoapEnv * env)
{
  xmlNsPtr ns;
  xmlNodePtr body, node;

  if (!(body = soap_env_get_body(env)))
  {
    log_verbose1("body is NULL");
    return 0;
  }

  /* node is the first child */
  if (!(node = soap_xml_get_children(body)))
  {
    log_error1("No namespace found");
    return 0;
  }

  /* if (node->ns && node->ns->prefix) MRC 1/25/2006 */
  if (node->ns)
  {
    ns = xmlSearchNs(body->doc, node, node->ns->prefix);
    if (ns != NULL)
    {
      return((char *) ns->href); /* namespace found! */
    }
  }
  else
  {
    static char *empty = "";
    log_warn1("No namespace found");
    return(empty);
  }

  return 0;
}
Beispiel #14
0
void *reader_thread(void *arg)
{
  SoapCtx *ctx, *ctx2;
  xmlNodePtr xmlcur,xmlitem,xmlitem2;
  herror_t err;
  char *itemname,*itemvalue,buf[1024], *cptr;
  int ret;
  THREAD_PARAM *p = (THREAD_PARAM *) arg;
  const char *url = (const char *) p->user;
  rlMailbox rlmbx(mbx);

  // read mbx until it is empty
  rlmbx.clear();
  printf("reader_thread starting\n");

  // wait for commands from clients
  while(1)
  {
    ret = rlmbx.read(buf,sizeof(buf)); // read "itemname,itemvalue\n"
    if(ret <= 0) continue;
    itemname = itemvalue = &buf[0];
    cptr = strchr(buf,',');
    if(cptr != NULL)
    {
      *cptr = '\0';
      cptr++;
      itemvalue = cptr;
      cptr = strchr(itemvalue,'\n');
      if(cptr != NULL) *cptr = 0;
    }
    if(debug)
    {
      printf("reader_thread Write itemname=%s itemvalue=%s\n",itemname,itemvalue);
    }

    p->thread->lock();

    /* create a SoapCtx object */
    err = soap_ctx_new_with_method(URN, "Write", &ctx);
    if (err != H_OK)
    {
      log_error4("%s():%s [%d]", herror_func(err),
                 herror_message(err), herror_code(err));
      herror_release(err);
      goto end_of_while;
    }

    /* create the ItemList */
    xmlitem = soap_env_add_item(ctx->env, "xsd:element", "ItemList", "");

    xmlcur = ctx->env->cur;
    ctx->env->cur = xmlitem;
    xmlitem2 = soap_env_add_item(ctx->env, "xsd:string", "Items", NULL);
    if (!xmlNewProp(xmlitem2, BAD_CAST "ItemName", BAD_CAST itemname))
    {
      log_error1("Can not create new xml attribute ItemName");
      goto end_of_while;
    }
    ctx->env->cur = xmlitem2;
    if(isdigit(itemvalue[0]))
    {
      soap_env_add_item(ctx->env,"xsd:double","Value",itemvalue);
    }
    else if(strcmp(itemvalue, "true") == 0 || strcmp(itemvalue, "false") == 0)
    {
      soap_env_add_item(ctx->env, "xsd:boolean", "Value", itemvalue);
    }
    else
    {
      soap_env_add_item(ctx->env,"xsd:istring","Value",itemvalue);
    }
    ctx->env->cur = xmlitem;
    ctx->env->cur = xmlcur;

    /* invoke */
    err = soap_client_invoke(ctx, &ctx2, url, "");
    if (err != H_OK)
    {
      log_error4("[%d] %s(): %s ", herror_code(err),
                 herror_func(err), herror_message(err));
      herror_release(err);
      soap_ctx_free(ctx);
      goto end_of_while;
    }

    /* print the result */
    if(debug)
    {
      printf("reader_thread result:\n");
      soap_xml_doc_print(ctx2->env->root->doc);
    }  

end_of_while:
    /* free the objects */
    soap_ctx_free(ctx2);
    soap_ctx_free(ctx);

    p->thread->unlock();
  }
  return NULL;
}
herror_t
mime_get_attachments(content_type_t * ctype, http_input_stream_t * in,
                     attachments_t ** dest)
{
  /* MIME variables */
  attachments_t *mimeMessage;
  part_t *part, *tmp_part = NULL;
  char *boundary, *root_id;

  /* Check for MIME message */
  if (!(ctype && !strcmp(ctype->type, "multipart/related")))
    return herror_new("mime_get_attachments", MIME_ERROR_NOT_MIME_MESSAGE,
                      "Not a MIME message '%s'", ctype->type);

  boundary = hpairnode_get(ctype->params, "boundary");
  root_id = hpairnode_get(ctype->params, "start");
  if (boundary == NULL)
  {
    /* TODO (#1#): Handle Error in http form */
    log_error1("'boundary' not set for multipart/related");
    return herror_new("mime_get_attachments", MIME_ERROR_NO_BOUNDARY_PARAM,
                      "'boundary' not set for multipart/related");
  }

  if (root_id == NULL)
  {
    /* TODO (#1#): Handle Error in http form */
    log_error1("'start' not set for multipart/related");
    return herror_new("mime_get_attachments", MIME_ERROR_NO_START_PARAM,
                      "'start' not set for multipart/related");
  }

  mimeMessage =
    mime_message_parse(in, root_id, boundary, ".");
  if (mimeMessage == NULL)
  {
    /* TODO (#1#): Handle Error in http form */
    log_error1("MIME Parse Error");
    return herror_new("mime_get_attachments", MIME_ERROR_PARSE_ERROR,
                      "MIME Parse Error");
  }

  /* Find root */
  if (!mimeMessage->root_part)
  {
    attachments_free(mimeMessage);
    return herror_new("mime_get_attachments", MIME_ERROR_NO_ROOT_PART,
                      "No root part found!");
  }

  /* delete root_part from list */
  part = mimeMessage->parts;
  while (part)
  {
    if (part == mimeMessage->root_part)
    {
      if (tmp_part)
        tmp_part->next = part->next;
      else
        mimeMessage->parts = part->next;

      break;
    }
    tmp_part = part;
    part = part->next;
  }
  *dest = mimeMessage;
  return H_OK;
}
static void
_mime_received_bytes(void *data, const unsigned char *bytes, int size)
{
  int i = 0;
  char *id, *type, *location;
  mime_callback_data_t *cbdata = (mime_callback_data_t *) data;

  if (!cbdata)
  {
    log_error1
      ("MIME transport error Called <received bytes> without initializing\n");
    return;
  }
  if (!cbdata->current_part)
  {
    log_error1
      ("MIME transport error Called <received bytes> without initializing\n");
    return;
  }
/*  log_verbose4("Received %d bytes (%p), header_search = %d", 
    size, data, cbdata->header_search);
*/
  if (cbdata->header_search < 4)
  {
    /* Find \r\n\r\n in bytes */
    for (i = 0; i < size; i++)
    {
      if (cbdata->header_search == 0)
      {
        if (bytes[i] == '\r')
          cbdata->header_search++;
        else
        {
          cbdata->header[cbdata->header_index++] = bytes[i];
          cbdata->header_search = 0;
        }
      }

      else if (cbdata->header_search == 1)
      {
        if (bytes[i] == '\n')
          cbdata->header_search++;
        else
        {
          cbdata->header[cbdata->header_index++] = '\r';
          cbdata->header[cbdata->header_index++] = bytes[i];
          cbdata->header_search = 0;
        }
      }

      else if (cbdata->header_search == 2)
      {
        if (bytes[i] == '\r')
          cbdata->header_search++;
        else
        {
          cbdata->header[cbdata->header_index++] = '\r';
          cbdata->header[cbdata->header_index++] = '\n';
          cbdata->header[cbdata->header_index++] = bytes[i];
          cbdata->header_search = 0;
        }
      }

      else if (cbdata->header_search == 3)
      {
        if (bytes[i] == '\n')
        {
          cbdata->header[cbdata->header_index++] = '\r';
          cbdata->header[cbdata->header_index++] = '\n';
          cbdata->header[cbdata->header_index++] = '\0';
          cbdata->header_search = 4;
          cbdata->current_part->header = _mime_process_header(cbdata->header);
          hpairnode_dump_deep(cbdata->current_part->header);
          /* set id */
          id = hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_ID);
          if (id != NULL)
          {
            strcpy(cbdata->current_part->id, id);
            if (!strcmp(id, cbdata->root_id))
              cbdata->message->root_part = cbdata->current_part;
          }
          location =
            hpairnode_get(cbdata->current_part->header,
                          HEADER_CONTENT_LOCATION);
          if (location != NULL)
          {
            strcpy(cbdata->current_part->location, location);
          }
          type =
            hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_TYPE);
          if (type != NULL)
          {
            strcpy(cbdata->current_part->content_type, type);
          }
          i++;
          break;
        }
        else
        {
          cbdata->header[cbdata->header_index++] = '\r';
          cbdata->header[cbdata->header_index++] = '\n';
          cbdata->header[cbdata->header_index++] = '\r';
          cbdata->header[cbdata->header_index++] = bytes[i];
          cbdata->header_search = 0;
        }
      }
      /* TODO (#1#): Check for cbdata->header overflow */

    }                           /* for (i=0;i<size;i++) */
  }                             /* if (cbdata->header_search < 4) */

  if (i >= size - 1)
    return;

  /* Write remaining bytes into the file or buffer (if root) (buffer is
     disabled in this version) */
  if (cbdata->current_fd)
    fwrite(&(bytes[i]), 1, size - i, cbdata->current_fd);
}
herror_t
hurl_parse(hurl_t * url, const char *urlstr)
{
  int iprotocol;
  int ihost;
  int iport;
  int len;
  int size;
  char tmp[8];
  char protocol[1024];

  iprotocol = 0;
  len = strlen(urlstr);

  /* find protocol */
  while (urlstr[iprotocol] != ':' && urlstr[iprotocol] != '\0')
  {
    iprotocol++;
  }

  if (iprotocol == 0)
  {
    log_error1("no protocol");
    return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol");
  }
  if (iprotocol + 3 >= len)
  {
    log_error1("no host");
    return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host");
  }
  if (urlstr[iprotocol] != ':'
      && urlstr[iprotocol + 1] != '/' && urlstr[iprotocol + 2] != '/')
  {
    log_error1("no protocol");
    return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol");
  }
  /* find host */
  ihost = iprotocol + 3;
  while (urlstr[ihost] != ':'
         && urlstr[ihost] != '/' && urlstr[ihost] != '\0')
  {
    ihost++;
  }

  if (ihost == iprotocol + 1)
  {
    log_error1("no host");
    return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host");
  }
  /* find port */
  iport = ihost;
  if (ihost + 1 < len)
  {
    if (urlstr[ihost] == ':')
    {
      while (urlstr[iport] != '/' && urlstr[iport] != '\0')
      {
        iport++;
      }
    }
  }

  /* find protocol */
  strncpy(protocol, urlstr, iprotocol);
  protocol[iprotocol] = '\0';
  if (strcmpigcase(protocol, "http"))
    url->protocol = PROTOCOL_HTTP;
  else if (strcmpigcase(protocol, "https"))
    url->protocol = PROTOCOL_HTTPS;
  else if (strcmpigcase(protocol, "ftp"))
    url->protocol = PROTOCOL_FTP;
  else
    return herror_new("hurl_parse",
                      URL_ERROR_UNKNOWN_PROTOCOL, "Unknown protocol '%s'",
                      protocol);

  /* TODO (#1#): add max of size and URL_MAX_HOST_SIZE */
  size = ihost - iprotocol - 3;
  strncpy(url->host, &urlstr[iprotocol + 3], size);
  url->host[size] = '\0';

  if (iport > ihost)
  {
    size = iport - ihost;
    strncpy(tmp, &urlstr[ihost + 1], size);
    url->port = atoi(tmp);
  }
  else
  {
    switch (url->protocol)
    {
    case PROTOCOL_HTTP:
      url->port = URL_DEFAULT_PORT_HTTP;
      break;
    case PROTOCOL_HTTPS:
      url->port = URL_DEFAULT_PORT_HTTPS;
      break;
    case PROTOCOL_FTP:
      url->port = URL_DEFAULT_PORT_FTP;
      break;
    }
  }

  len = strlen(urlstr);
  if (len > iport)
  {
    /* TODO (#1#): find max of size and URL_MAX_CONTEXT_SIZE */
    size = len - iport;
    strncpy(url->context, &urlstr[iport], size);
    url->context[size] = '\0';
  }
  else
  {
    url->context[0] = '\0';
  }

  hurl_dump(url);

  return H_OK;
}
/*--------------------------------------------------
FUNCTION: httpc_talk_to_server
DESC: This function is the heart of the httpc
module. It will send the request and process the
response.

Here the parameters:

method:
the request method. This can be HTTP_REQUEST_POST and
HTTP_REQUEST_GET.

conn:
the connection object (created with httpc_new())

urlstr:
the complete url in string format.
http://<host>:<port>/<context>
where <port> is not mendatory.

start_cb:
a callback function, which will be called when
the response header is completely arrives.

cb:
a callback function, which will be called everytime
when data arrives.

content_size:
size of content to send.
(only if method is HTTP_REQUEST_POST)

content:
the content data to send.
(only if method is HTTP_REQUEST_POST)

userdata:
a user define data, which will be passed to the
start_cb and cb callbacks as a parameter. This
can also be NULL.


If success, this function will return 0.
>0 otherwise.
----------------------------------------------------*/
static herror_t
httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn,
                     const char *urlstr)
{

  hurl_t url;
  char buffer[4096];
  herror_t status;
  int ssl;

  if (conn == NULL)
  {
    return herror_new("httpc_talk_to_server",
                      GENERAL_INVALID_PARAM, "httpc_conn_t param is NULL");
  }
  /* Build request header */
  httpc_header_set_date(conn);

  if ((status = hurl_parse(&url, urlstr)) != H_OK)
  {
    log_error2("Can not parse URL '%s'", SAVE_STR(urlstr));
    return status;
  }
/* TODO (#1#): Check for HTTP protocol in URL */

  /* Set hostname */
  httpc_set_header(conn, HEADER_HOST, url.host);

  ssl = url.protocol == PROTOCOL_HTTPS ? 1 : 0;

  /* Open connection */
  if ((status = hsocket_open(&conn->sock, url.host, url.port, ssl)) != H_OK)
    return status;

  switch(method)
  {
    case HTTP_REQUEST_GET:

      sprintf(buffer, "GET %s HTTP/%s\r\n",
        (url.context[0] != '\0') ? url.context : ("/"),
        (conn->version == HTTP_1_0) ? "1.0" : "1.1");
      break;

    case HTTP_REQUEST_POST:

      sprintf(buffer, "POST %s HTTP/%s\r\n",
        (url.context[0] != '\0') ? url.context : ("/"),
        (conn->version == HTTP_1_0) ? "1.0" : "1.1");
      break;

    default:
      log_error1("Unknown method type!");
      return herror_new("httpc_talk_to_server",
        GENERAL_INVALID_PARAM,
        "hreq_method_t must be  HTTP_REQUEST_GET or HTTP_REQUEST_POST");
  }

  log_verbose1("Sending request...");
  if ((status = hsocket_send(&(conn->sock), buffer)) != H_OK)
  {
    log_error2("Cannot send request (%s)", herror_message(status));
    hsocket_close(&(conn->sock));
    return status;
  }

  log_verbose1("Sending header...");
  if ((status = httpc_send_header(conn)) != H_OK)
  {
    log_error2("Cannot send header (%s)", herror_message(status));
    hsocket_close(&(conn->sock));
    return status;
  }

  return H_OK;
}