예제 #1
0
파일: zxidcurl.c 프로젝트: gitpan/zxid
/* Called by:  zxid_soap_call_hdr_body, zxid_wsc_call */
struct zx_root_s* zxid_soap_call_raw(zxid_conf* cf, struct zx_str* url, struct zx_e_Envelope_s* env, char** ret_enve)
{
#ifdef USE_CURL
  struct zx_root_s* r;
  struct zx_str* ret;
  struct zx_str* ss;
  char soap_action_buf[1024];
  char* soap_act;
  const char* env_start;

  ss = zx_easy_enc_elem_opt(cf, &env->gg);
  DD("ss(%.*s) len=%d", ss->len, ss->s, ss->len);

  if (cf->soap_action_hdr && strcmp(cf->soap_action_hdr,"#inhibit")) {
    if (!strcmp(cf->soap_action_hdr,"#same")) {
      if (env->Header && env->Header->Action && ZX_GET_CONTENT_S(env->Header->Action)) {
	snprintf(soap_action_buf,sizeof(soap_action_buf), "SOAPAction: \"%.*s\"", ZX_GET_CONTENT_LEN(env->Header->Action), ZX_GET_CONTENT_S(env->Header->Action));
	soap_action_buf[sizeof(soap_action_buf)-1] = 0;
	soap_act = soap_action_buf;
	D("SOAPaction(%s)", soap_action_buf);
      } else {
	ERR("e:Envelope/e:Headers/a:Action SOAP header is malformed %p", env->Header);
      }
    } else {
      snprintf(soap_action_buf,sizeof(soap_action_buf), "SOAPAction: \"%s\"", cf->soap_action_hdr);
      soap_action_buf[sizeof(soap_action_buf)-1] = 0;
      soap_act = soap_action_buf;
    }
  } else
    soap_act = 0;
  
  ret = zxid_http_cli(cf, url->len, url->s, ss->len, ss->s, cf->wsc_soap_content_type, soap_act, 0);
  zx_str_free(cf->ctx, ss);
  if (ret_enve)
    *ret_enve = ret?ret->s:0;
  if (!ret)
    return 0;
  
  env_start = zxid_locate_soap_Envelope(ret->s);
  if (!env_start) {
    ERR("SOAP response does not have Envelope element url(%.*s)", url->len, url->s);
    D_XML_BLOB(cf, "NO ENVELOPE SOAP RESPONSE", ret->len, ret->s);
    ZX_FREE(cf->ctx, ret);
    return 0;
  }

  cf->ctx->top1 = 1;  /* Stop parsing after first toplevel <e:Envelope> */
  r = zx_dec_zx_root(cf->ctx, ret->len - (env_start - ret->s), env_start, "soap_call");
  if (!r || !r->Envelope || !r->Envelope->Body) {
    ERR("Failed to parse SOAP response url(%.*s)", url->len, url->s);
    D_XML_BLOB(cf, "BAD SOAP RESPONSE", ret->len, ret->s);
    ZX_FREE(cf->ctx, ret);
    return 0;
  }
  return r;
#else
  ERR("This copy of zxid was compiled to NOT use libcurl. SOAP calls (such as Artifact profile and WSC) are not supported. Add -DUSE_CURL (make ENA_CURL=1) and recompile. %d", 0);
  return 0;
#endif
}
예제 #2
0
파일: zxidcurl.c 프로젝트: gitpan/zxid
/* Called by: */
size_t zxid_curl_write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
  int len = size * nmemb;
#if 1
  struct zxid_curl_ctx* rc = (struct zxid_curl_ctx*)userp;
  int old_len, new_len, in_buf = rc->p - rc->buf;
  if (rc->p + len > rc->lim) {
    old_len = rc->lim-rc->buf;
    new_len = MIN(MAX(old_len + old_len, in_buf + len), ZXID_MAX_CURL_BUF);
    if (new_len == ZXID_MAX_CURL_BUF) {
      ERR("Too large HTTP response. Response length at least %d. Maximum allowed length (ZXID_MAX_CURL_BUF): %d", in_buf + len, ZXID_MAX_CURL_BUF);
      return -1;  /* Signal error */
    }
    D("Reallocating curl buffer from %d to %d in_buf=%d len=%d", old_len, new_len, in_buf, len);
    REALLOCN(rc->buf, new_len+1);
    rc->p = rc->buf + in_buf;
    rc->lim = rc->buf + new_len;
  }
  memcpy(rc->p, buffer, len);
  rc->p += len;
  if (errmac_debug & CURL_INOUT) {
    INFO("RECV(%.*s) %d chars", len, (char*)buffer, len);
    D_XML_BLOB(0, "RECV", len, (char*)buffer);
  }
#else
  int fd = (int)userp;
  write_all_fd(fd, buffer, len);
#endif
  return len;
}
예제 #3
0
파일: zxidcurl.c 프로젝트: gitpan/zxid
/* Called by: */
size_t zxid_curl_read_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
  int len = size*nmemb;
  struct zxid_curl_ctx* wc = (struct zxid_curl_ctx*)userp;
  if (len > (wc->lim - wc->p))
    len = wc->lim - wc->p;
  memcpy(buffer, wc->p, len);
  wc->p += len;
  if (errmac_debug & CURL_INOUT) {
    INFO("SEND(%.*s) %d chars", len, (char*)buffer, len);
    D_XML_BLOB(0, "SEND", len, (char*)buffer);
  }
  return len;
}
예제 #4
0
파일: zxidcurl.c 프로젝트: gitpan/zxid
/* Called by:  zxid_soap_call_raw */
struct zx_str* zxid_http_cli(zxid_conf* cf, int url_len, const char* url, int len, const char* data, const char* content_type, const char* headers, int flags)
{
#ifdef USE_CURL
  struct zx_str* ret;
  CURLcode res;
  struct zxid_curl_ctx rc;
  struct zxid_curl_ctx wc;
  struct curl_slist content_type_curl;
  struct curl_slist headers_curl;
  char* urli;
  rc.buf = rc.p = ZX_ALLOC(cf->ctx, ZXID_INIT_SOAP_BUF+1);
  rc.lim = rc.buf + ZXID_INIT_SOAP_BUF;

  /* The underlying HTTP client is libcurl. While libcurl is documented to
   * be "entirely thread safe", one limitation is that curl handle can not
   * be shared between threads. Since we keep the curl handle as a part
   * of the configuration object, which may be shared between threads,
   * we need to take a lock for duration of the curl operation. Thus any
   * given configuration object can have only one HTTP request active
   * at a time. If you need more parallelism, you need more configuration
   * objects.
   */

#if 0
  cf->curl = curl_easy_init();
  curl_easy_reset(cf->curl);
  LOCK_INIT(cf->curl_mx);
  LOCK(cf->curl_mx, "curl-cli");
#else
  LOCK(cf->curl_mx, "curl-cli");
  curl_easy_reset(cf->curl);
#endif

  curl_easy_setopt(cf->curl, CURLOPT_WRITEDATA, &rc);
  curl_easy_setopt(cf->curl, CURLOPT_WRITEFUNCTION, zxid_curl_write_data);
  curl_easy_setopt(cf->curl, CURLOPT_NOPROGRESS, 1);
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYPEER, 0);  /* *** arrange verification */
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYHOST, 0);  /* *** arrange verification */
  //curl_easy_setopt(cf->curl, CURLOPT_CERTINFO, 1);

  if (!(flags & 0x02)) {
    curl_easy_setopt(cf->curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(cf->curl, CURLOPT_MAXREDIRS, 110);
  }
  
  if (flags & 0x01)
    curl_easy_setopt(cf->curl, CURLOPT_HEADER, 1); /* response shall have Heacers CRLF CRLF Body */

  if (url_len == -1)
    url_len = strlen(url);
  urli = ZX_ALLOC(cf->ctx, url_len+1);
  memcpy(urli, url, url_len);
  urli[url_len] = 0;
  DD("urli(%s) len=%d", urli, len);
  curl_easy_setopt(cf->curl, CURLOPT_URL, urli);
  
  if (data) {
    if (len == -1)
      len = strlen(data);
    wc.buf = wc.p = (char*)data;
    wc.lim = (char*)data + len;
  
    curl_easy_setopt(cf->curl, CURLOPT_POST, 1);
    curl_easy_setopt(cf->curl, CURLOPT_POSTFIELDSIZE, len);
    curl_easy_setopt(cf->curl, CURLOPT_READDATA, &wc);
    curl_easy_setopt(cf->curl, CURLOPT_READFUNCTION, zxid_curl_read_data);
  
    ZERO(&content_type_curl, sizeof(content_type_curl));
    content_type_curl.data = (char*)content_type;
    if (headers) {
      ZERO(&headers_curl, sizeof(headers_curl));
      headers_curl.data = (char*)headers;
      headers_curl.next = &content_type_curl;    //curl_slist_append(3)
      curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &headers_curl);
    } else {
      curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &content_type_curl);
    }
  } else {
    if (headers) {
      ZERO(&headers_curl, sizeof(headers_curl));
      headers_curl.data = (char*)headers;
      curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &headers_curl);
    }
  }
  
  INFO("----------- call(%s) -----------", urli);
  DD("HTTP_CLI post(%.*s) len=%d\n", len, STRNULLCHK(data), len);
  D_XML_BLOB(cf, "HTTP_CLI POST", len, STRNULLCHK(data));
  res = curl_easy_perform(cf->curl);  /* <========= Actual call, blocks. */
  switch (res) {
  case 0: break;
  case CURLE_SSL_CONNECT_ERROR:
    ERR("Is the URL(%s) really an https url? Check that certificate of the server is valid and that certification authority is known to the client. CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
#if 0
    struct curl_certinfo* ci;
    res = curl_easy_getinfo(cf->curl, CURLINFO_CERTINFO, &ci);  /* CURLINFO_SSL_VERIFYRESULT */
    if (!res && ci) {
      int i;
      struct curl_slist *slist;
      D("%d certs", ci->num_of_certs);
      for (i = 0; i < ci->num_of_certs; ++i)
	for (slist = ci->certinfo[i]; slist; slist = slist->next)
	  D("%d: %s", i, slist->data);
    }
#endif
    break;
  default:
    ERR("Failed post to url(%s) CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
  }

  /*curl_easy_getinfo(cf->curl, CURLINFO_CONTENT_TYPE, char*);*/

  UNLOCK(cf->curl_mx, "curl-cli");
  ZX_FREE(cf->ctx, urli);
  rc.lim = rc.p;
  rc.p[0] = 0;

  DD("HTTP_CLI got(%s)", rc.buf);
  DD_XML_BLOB(cf, "HTTP_CLI GOT", rc.lim - rc.buf, rc.buf);
  
  ret = zx_ref_len_str(cf->ctx, rc.lim - rc.buf, rc.buf);
  return ret;
#else
  ERR("This copy of zxid was compiled to NOT use libcurl. SOAP calls (such as Artifact profile and WSC) are not supported. Add -DUSE_CURL (make ENA_CURL=1) and recompile. %d", 0);
  return 0;
#endif
}
예제 #5
0
파일: zxidcurl.c 프로젝트: grubba/zxid
/* Called by:  zxid_soap_call_raw */
struct zx_str* zxid_http_post_raw(zxid_conf* cf, int url_len, const char* url, int len, const char* data, const char* SOAPaction)
{
#ifdef USE_CURL
  struct zx_str* ret;
  CURLcode res;
  struct zxid_curl_ctx rc;
  struct zxid_curl_ctx wc;
  struct curl_slist content_type;
  struct curl_slist SOAPaction_curl;
  char* urli;
  rc.buf = rc.p = ZX_ALLOC(cf->ctx, ZXID_INIT_SOAP_BUF+1);
  rc.lim = rc.buf + ZXID_INIT_SOAP_BUF;
#if 0
  cf->curl = curl_easy_init();
  curl_easy_reset(cf->curl);
  LOCK_INIT(cf->curl_mx);
  LOCK(cf->curl_mx, "curl-soap");
#else
  LOCK(cf->curl_mx, "curl-soap");
  curl_easy_reset(cf->curl);
#endif
  curl_easy_setopt(cf->curl, CURLOPT_WRITEDATA, &rc);
  curl_easy_setopt(cf->curl, CURLOPT_WRITEFUNCTION, zxid_curl_write_data);
  curl_easy_setopt(cf->curl, CURLOPT_NOPROGRESS, 1);
  curl_easy_setopt(cf->curl, CURLOPT_FOLLOWLOCATION, 1);
  curl_easy_setopt(cf->curl, CURLOPT_MAXREDIRS, 110);
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYPEER, 0);  /* *** arrange verification */
  curl_easy_setopt(cf->curl, CURLOPT_SSL_VERIFYHOST, 0);  /* *** arrange verification */
  //curl_easy_setopt(cf->curl, CURLOPT_CERTINFO, 1);

  if (url_len == -1)
    url_len = strlen(url);
  urli = ZX_ALLOC(cf->ctx, url_len+1);
  memcpy(urli, url, url_len);
  urli[url_len] = 0;
  DD("urli(%s) len=%d", urli, len);
  curl_easy_setopt(cf->curl, CURLOPT_URL, urli);
  
  if (len == -1)
    len = strlen(data);
  wc.buf = wc.p = (char*)data;
  wc.lim = (char*)data + len;
  
  curl_easy_setopt(cf->curl, CURLOPT_POST, 1);
  curl_easy_setopt(cf->curl, CURLOPT_POSTFIELDSIZE, len);
  curl_easy_setopt(cf->curl, CURLOPT_READDATA, &wc);
  curl_easy_setopt(cf->curl, CURLOPT_READFUNCTION, zxid_curl_read_data);

  ZERO(&content_type, sizeof(content_type));
  content_type.data = cf->wsc_soap_content_type; /* SOAP11: "Content-Type: text/xml" */
  if (SOAPaction) {
    ZERO(&SOAPaction_curl, sizeof(SOAPaction_curl));
    SOAPaction_curl.data = (char*)SOAPaction;
    SOAPaction_curl.next = &content_type;    //curl_slist_append(3)
    curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &SOAPaction_curl);
  } else {
    curl_easy_setopt(cf->curl, CURLOPT_HTTPHEADER, &content_type);
  }
  
  INFO("----------- call(%s) -----------", urli);
  DD("SOAP_CALL post(%.*s) len=%d\n", len, data, len);
  D_XML_BLOB(cf, "SOAPCALL POST", len, data);
  res = curl_easy_perform(cf->curl);  /* <========= Actual call, blocks. */
  switch (res) {
  case 0: break;
  case CURLE_SSL_CONNECT_ERROR:
    ERR("Is the URL(%s) really an https url? Check that certificate of the server is valid and that certification authority is known to the client. CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
#if 0
    struct curl_certinfo* ci;
    res = curl_easy_getinfo(cf->curl, CURLINFO_CERTINFO, &ci);  /* CURLINFO_SSL_VERIFYRESULT */
    if (!res && ci) {
      int i;
      struct curl_slist *slist;
      D("%d certs", ci->num_of_certs);
      for (i = 0; i < ci->num_of_certs; ++i)
	for (slist = ci->certinfo[i]; slist; slist = slist->next)
	  D("%d: %s", i, slist->data);
    }
#endif
    break;
  default:
    ERR("Failed post to url(%s) CURLcode(%d) CURLerr(%s)", urli, res, CURL_EASY_STRERR(res));
    DD("buf(%.*s)", rc.lim-rc.buf, rc.buf);
  }

  /*curl_easy_getinfo(cf->curl, CURLINFO_CONTENT_TYPE, char*);*/

  UNLOCK(cf->curl_mx, "curl-soap");
  ZX_FREE(cf->ctx, urli);
  rc.lim = rc.p;
  rc.p[0] = 0;

  DD("SOAP_CALL got(%s)", rc.buf);
  D_XML_BLOB(cf, "SOAPCALL GOT", rc.lim - rc.buf, rc.buf);
  
  ret = zx_ref_len_str(cf->ctx, rc.lim - rc.buf, rc.buf);
  return ret;
#else
  ERR("This copy of zxid was compiled to NOT use libcurl. SOAP calls (such as Artifact profile and WSC) are not supported. Add -DUSE_CURL (make ENA_CURL=1) and recompile. %d", 0);
  return 0;
#endif
}