コード例 #1
0
ファイル: csync_owncloud.c プロジェクト: gco/csync
static void install_content_reader( ne_request *req, void *userdata, const ne_status *status )
{
    const char *enc = NULL;
    struct transfer_context *writeCtx = userdata;

    (void) status;
    if( !writeCtx ) {
        DEBUG_WEBDAV("Error: install_content_reader called without valid write context!");
        return;
    }

    enc = ne_get_response_header( req, "Content-Encoding" );
    if( status && status->code != 200 ) {
      DEBUG_WEBDAV("Content encoding ist <%s> with status %d", enc ? enc : "empty",
                   status ? status->code : -1 );
    }

    if( enc && c_streq( enc, "gzip" )) {
        writeCtx->decompress = ne_decompress_reader( req, ne_accept_2xx,
                                                     compress_reader,     /* reader callback */
                                                     (void*) writeCtx );  /* userdata        */
    } else {
        ne_add_response_body_reader( req, ne_accept_2xx,
                                     uncompress_reader,
                                     (void*) writeCtx );
        writeCtx->decompress = NULL;
    }
}
コード例 #2
0
ファイル: ne_basic.c プロジェクト: cern-it-sdc-id/davix
int ne_getmodtime(ne_session *sess, const char *uri, time_t *modtime)
{
    ne_request *req = ne_request_create(sess, "HEAD", uri);
    const char *value;
    int ret;

    ret = ne_request_dispatch(req);

    value = ne_get_response_header(req, "Last-Modified");

    if (ret == NE_OK && ne_get_status(req)->klass != 2) {
	*modtime = -1;
	ret = NE_ERROR;
    }
    else if (value) {
        *modtime = ne_httpdate_parse(value);
    }
    else {
        *modtime = -1;
    }

    ne_request_destroy(req);

    return ret;
}
コード例 #3
0
ファイル: ne_basic.c プロジェクト: tolsen/limeberry
/* Dispatch a GET request REQ, writing the response body to FD fd.  If
 * RANGE is non-NULL, then it is the value of the Range request
 * header, e.g. "bytes=1-5".  Returns an NE_* error code. */
static int dispatch_to_fd(ne_request *req, int fd, const char *range)
{
    ne_session *const sess = ne_get_session(req);
    const ne_status *const st = ne_get_status(req);
    int ret;

    do {
        const char *value;
        
        ret = ne_begin_request(req);
        if (ret != NE_OK) break;

        value = ne_get_response_header(req, "Content-Range");

        /* For a 206 response, check that a Content-Range header is
         * given which matches the Range request header. */
        if (range && st->code == 206 
            && (value == NULL || strncmp(value, "bytes ", 6) != 0
                || strcmp(range + 6, value + 6))) {
            ne_set_error(sess, _("Response did not include requested range"));
            return NE_ERROR;
        }

        if ((range && st->code == 206) || (!range && st->klass == 2)) {
            ret = ne_read_response_to_fd(req, fd);
        } else {
            ret = ne_discard_response(req);
        }

        if (ret == NE_OK) ret = ne_end_request(req);
    } while (ret == NE_RETRY);

    return ret;
}
コード例 #4
0
static int accept(void* userdata, ne_request* req, const ne_status* st) {
    ne_userdata* u   = reinterpret_cast<ne_userdata*>(userdata);
    auto         len = ne_get_response_header(req, "Content-Length");
    (void)u;
    (void)len;
    return true;
}
コード例 #5
0
ファイル: util.c プロジェクト: DJEX93/dsploit
const char *
svn_ra_neon__request_get_location(svn_ra_neon__request_t *request,
                                  apr_pool_t *pool)
{
  const char *val = ne_get_response_header(request->ne_req, "Location");
  return val ? svn_urlpath__canonicalize(val, pool) : NULL;
}
コード例 #6
0
ファイル: libs3.c プロジェクト: soundsrc/s3nbd
int s3_head_object(S3 *s3,const char *bucket,const char *key,S3ObjectInfo *oi)
{
	ne_request *req;
	int err;

	if(!s3) return -1;
	if(!bucket) return -1;

	s3_begin_session(s3);

	req = s3_new_request(s3,"HEAD",bucket,key,NULL,NULL);

	// send to server
	err = ne_request_dispatch(req);
	if(err != NE_OK) err = -EIO;

	if(ne_get_status(req)->code != 200) {
		s3_handle_error_response(s3,req);
		if(ne_get_status(req)->code == 404) err = -ENOENT;
		else err = -EACCES;
	} else if(oi) {
		const char *str;
		str = ne_get_response_header(req,"Content-Length");
		if(str) oi->content_length = strtol(str,NULL,10);
		str = ne_get_response_header(req,"Content-Type");
		if(str) {
			strncpy(oi->content_type,str,31);
			oi->content_type[31] = 0;
		}
		str = ne_get_response_header(req,"ETag");
		if(str) {
			strncpy(oi->etag,str,79);
			oi->etag[79] = 0;
		}
	}

	ne_request_destroy(req);
	s3_end_session(s3);

	return err;
}
コード例 #7
0
ファイル: ne_basic.c プロジェクト: cern-it-sdc-id/davix
int ne_get_content_type(ne_request *req, ne_content_type *ct)
{
    const char *value;
    char *sep, *stype;

    value = ne_get_response_header(req, "Content-Type");
    if (value == NULL || strchr(value, '/') == NULL) {
        return -1;
    }

    ct->value = ne_strdup(value);

    stype = strchr(ct->value, '/');

    *stype++ = '\0';
    ct->type = ct->value;
    ct->charset = NULL;

    sep = strchr(stype, ';');

    if (sep) {
	char *tok;
	/* look for the charset parameter. TODO; probably better to
	 * hand-carve a parser than use ne_token/strstr/shave here. */
	*sep++ = '\0';
	do {
	    tok = ne_qtoken(&sep, ';', "\"\'");
	    if (tok) {
		tok = strstr(tok, "charset=");
		if (tok)
		    ct->charset = ne_shave(tok+8, "\"\'");
	    } else {
		break;
	    }
	} while (sep != NULL);
    }

    /* set subtype, losing any trailing whitespace */
    ct->subtype = ne_shave(stype, " \t");

    if (ct->charset == NULL && ne_strcasecmp(ct->type, "text") == 0) {
        /* 3280§3.1: text/xml without charset implies us-ascii. */
        if (ne_strcasecmp(ct->subtype, "xml") == 0)
            ct->charset = "us-ascii";
        /* 2616§3.7.1: subtypes of text/ default to charset ISO-8859-1. */
        else
            ct->charset = "ISO-8859-1";
    }

    return 0;
}
コード例 #8
0
ファイル: ne_basic.c プロジェクト: elambert/honeycomb
/* Dispatch a GET request REQ, writing the response body to FD fd.  If
 * RANGE is non-NULL, then it is the value of the Range request
 * header, e.g. "bytes=1-5".  Returns an NE_* error code. */
static int dispatch_to_fd(ne_request *req, int fd, const char *range)
{
    ne_session *const sess = ne_get_session(req);
    const ne_status *const st = ne_get_status(req);
    int ret;

    do {
        const char *value;
        
        ret = ne_begin_request(req);
        if (ret != NE_OK) break;

        value = ne_get_response_header(req, "Content-Range");

        /* For a 206 response, check that a Content-Range header is
         * given which matches the Range request header. */
        if (range && st->code == 206) {
            int err = 0;
            if (value == NULL || strncmp(value, "bytes ", 6) != 0) {
                err++;
            } else {
                /* If the response gives a range begin-end/total, limit
                 * the comparison to the range itself. */
                int len = strlen(value);
                char *cp = strchr(value, '/');
                if (cp != NULL)
                    len = (int)(cp - value);
                len -= 6;
                if (strncmp(range + 6, value + 6, len))
                    err++;
            }
            if (err) {
                ne_set_error(sess, _("Response did not include requested range"));
                return NE_ERROR;
            }
        }

        if ((range && st->code == 206) || (!range && st->klass == 2)) {
            ret = ne_read_response_to_fd(req, fd);
        } else {
            ret = ne_discard_response(req);
        }

        if (ret == NE_OK) ret = ne_end_request(req);
    } while (ret == NE_RETRY);

    return ret;
}
コード例 #9
0
ファイル: ne_basic.c プロジェクト: tolsen/limeberry
int ne_options(ne_session *sess, const char *uri, ne_server_capabilities *caps)
{
    ne_request *req = ne_request_create(sess, "OPTIONS", uri);
    int ret = ne_request_dispatch(req);
    const char *header = ne_get_response_header(req, "DAV");
    
    if (header) parse_dav_header(header, caps);
 
    if (ret == NE_OK && ne_get_status(req)->klass != 2) {
	ret = NE_ERROR;
    }
    
    ne_request_destroy(req);

    return ret;
}
コード例 #10
0
ファイル: ne_locks.c プロジェクト: elazzi/winscp
static int lk_startelm(void *userdata, int parent,
                       const char *nspace, const char *name,
		       const char **atts)
{
    struct lock_ctx *ctx = userdata;
    int id;
    NE_DEBUG_WINSCP_CONTEXT(ne_get_session(ctx->req));

    id = ne_xml_mapid(element_map, NE_XML_MAPLEN(element_map), nspace, name);

    NE_DEBUG(NE_DBG_LOCKS, "lk_startelm: %s => %d\n", name, id);
    
    if (id == 0)
        return NE_XML_DECLINE;    

    if (parent == 0 && ctx->token == NULL) {
        const char *token = ne_get_response_header(ctx->req, "Lock-Token");
        /* at the root element; retrieve the Lock-Token header,
         * and bail if it wasn't given. */
        if (token == NULL) {
            ne_xml_set_error(ctx->parser, 
                             _("LOCK response missing Lock-Token header"));
            return NE_XML_ABORT;
        }

        if (token[0] == '<') token++;
        ctx->token = ne_strdup(token);
        ne_shave(ctx->token, ">");
        NE_DEBUG(NE_DBG_LOCKS, "lk_startelm: Finding token %s\n",
                 ctx->token);
    }

    /* TODO: only accept 'prop' as root for LOCK response */
    if (!can_accept(parent, id))
        return NE_XML_DECLINE;

    if (id == ELM_activelock && !ctx->found) {
	/* a new activelock */
	ne_lock_free(&ctx->active);
	memset(&ctx->active, 0, sizeof ctx->active);
        ctx->active.timeout = NE_TIMEOUT_INVALID;
    }

    ne_buffer_clear(ctx->cdata);

    return id;
}
コード例 #11
0
ファイル: csync_owncloud.c プロジェクト: liusijiang/mirall
static int post_send_hook(ne_request *req, void *userdata,
                          const ne_status *status)
{
    const char *location;

    (void) userdata;
    (void) status;

    location = ne_get_response_header(req, "Location");

    if( !location ) return NE_OK;

    if( dav_session.redir_callback ) {
        if( dav_session.redir_callback( dav_session.csync_ctx, location ) ) {
            return NE_REDIRECT;
        } else {
            return NE_RETRY;
        }
    }

    return NE_REDIRECT;
}
コード例 #12
0
ファイル: buffer.c プロジェクト: almukora/Stratosphere
static int dispatch_to_buffer(ne_session *sess, ne_request *req, char *buf, const char *range, ssize_t *bytes_read)
{
    const ne_status *const st = ne_get_status(req);
    int ret;
    size_t rlen;

    /* length of bytespec after "bytes=" */
    rlen = range ? strlen(range + 6) : 0;

    do {
        const char *value;

        ret = ne_begin_request(req);
        if (ret != NE_OK) break;

        value = ne_get_response_header(req, "Content-Range");

        /* For a 206 response, check that a Content-Range header is
         * given which matches the Range request header. */
        if (range && st->code == 206
            && (value == NULL || strncmp(value, "bytes ", 6) != 0
                || strncmp(range + 6, value + 6, rlen)
                || (range[5 + rlen] != '-' && value[6 + rlen] != '/'))) {
            ne_set_error(sess, "Response did not include requested range");
            return NE_ERROR;
        }

        if ((range && st->code == 206) || (!range && st->klass == 2)) {
            ret = ne_read_response_to_buf(req, buf, bytes_read);
        } else {
            ret = ne_discard_response(req);
        }

        if (ret == NE_OK) ret = ne_end_request(req);
    } while (ret == NE_RETRY);

    return ret;
}
コード例 #13
0
ファイル: options.c プロジェクト: matthewdpklanier/alien-svn
/* Store in RAS the capabilities discovered from REQ's headers.
   Use POOL for temporary allocation only. */
static void
parse_capabilities(ne_request *req,
                   svn_ra_neon__session_t *ras,
                   apr_pool_t *pool)
{
  const char *header_value;

  /* Start out assuming all capabilities are unsupported. */
  apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_DEPTH,
               APR_HASH_KEY_STRING, capability_no);
  apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
               APR_HASH_KEY_STRING, capability_no);
  apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
               APR_HASH_KEY_STRING, capability_no);

  /* Then find out which ones are supported. */
  header_value = ne_get_response_header(req, "dav");
  if (header_value)
    {
      /* Multiple headers of the same name will have been merged
         together by the time we see them (either by an intermediary,
         as is permitted in HTTP, or by neon) -- merged in the sense
         that if a header "foo" appears multiple times, all the values
         will be concatenated together, with spaces at the splice
         points.  For example, if the server sent:

            DAV: 1,2
            DAV: version-control,checkout,working-resource
            DAV: merge,baseline,activity,version-controlled-collection
            DAV: http://subversion.tigris.org/xmlns/dav/svn/depth

          Here we might see:

          header_value == "1,2, version-control,checkout,working-resource, merge,baseline,activity,version-controlled-collection, http://subversion.tigris.org/xmlns/dav/svn/depth, <http://apache.org/dav/propset/fs/1>"

          (Deliberately not line-wrapping that, so you can see what
          we're about to parse.)
      */

      apr_array_header_t *vals =
        svn_cstring_split(header_value, ",", TRUE, pool);

      /* Right now we only have a few capabilities to detect, so
         just seek for them directly.  This could be written
         slightly more efficiently, but that wouldn't be worth it
         until we have many more capabilities. */

      if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
        apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_DEPTH,
                     APR_HASH_KEY_STRING, capability_yes);

      if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
        /* The server doesn't know what repository we're referring
           to, so it can't just say capability_yes. */
        apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
                     APR_HASH_KEY_STRING, capability_server_yes);

      if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
        apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
                     APR_HASH_KEY_STRING, capability_yes);

      if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY,
                                      vals))
        apr_hash_set(ras->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
                     APR_HASH_KEY_STRING, capability_yes);
    }
}
/* create a socket for connecting to remote server */
static gboolean
gst_neonhttp_src_start (GstBaseSrc * bsrc)
{
  GstNeonhttpSrc *src = GST_NEONHTTP_SRC (bsrc);
  const gchar *content_length;
  gint res;

#ifndef GST_DISABLE_GST_DEBUG
  if (src->neon_http_debug)
    ne_debug_init (stderr, NE_DBG_HTTP);
#endif

  ne_oom_callback (oom_callback);

  res = ne_sock_init ();
  if (res != 0)
    goto init_failed;

  res = gst_neonhttp_src_send_request_and_redirect (src,
      &src->session, &src->request, 0, src->automatic_redirect);

  if (res != NE_OK || !src->session) {
    if (res == HTTP_SOCKET_ERROR) {
      goto socket_error;
    } else if (res == HTTP_REQUEST_WRONG_PROXY) {
      goto wrong_proxy;
    } else {
      goto begin_req_failed;
    }
  }

  content_length = ne_get_response_header (src->request, "Content-Length");

  if (content_length)
    src->content_size = g_ascii_strtoull (content_length, NULL, 10);
  else
    src->content_size = -1;

  if (src->iradio_mode) {
    /* Icecast stuff */
    const gchar *str_value;
    gint gint_value;

    str_value = ne_get_response_header (src->request, "icy-metaint");
    if (str_value) {
      if (sscanf (str_value, "%d", &gint_value) == 1) {
        if (src->icy_caps) {
          gst_caps_unref (src->icy_caps);
          src->icy_caps = NULL;
        }
        src->icy_metaint = gint_value;
        src->icy_caps = gst_caps_new_simple ("application/x-icy",
            "metadata-interval", G_TYPE_INT, src->icy_metaint, NULL);
      }
    }

    str_value = ne_get_response_header (src->request, "icy-name");
    if (str_value) {
      if (src->iradio_name) {
        g_free (src->iradio_name);
        src->iradio_name = NULL;
      }
      src->iradio_name = gst_neonhttp_src_unicodify (str_value);
    }
    str_value = ne_get_response_header (src->request, "icy-genre");
    if (str_value) {
      if (src->iradio_genre) {
        g_free (src->iradio_genre);
        src->iradio_genre = NULL;
      }
      src->iradio_genre = gst_neonhttp_src_unicodify (str_value);
    }
    str_value = ne_get_response_header (src->request, "icy-url");
    if (str_value) {
      if (src->iradio_url) {
        g_free (src->iradio_url);
        src->iradio_url = NULL;
      }
      src->iradio_url = gst_neonhttp_src_unicodify (str_value);
    }
  }

  return TRUE;

  /* ERRORS */
init_failed:
  {
    GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
        ("ne_sock_init() failed: %d", res));
    return FALSE;
  }
socket_error:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
        ("HTTP Request failed when opening socket: %d", res));
    return FALSE;
  }
wrong_proxy:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
        ("Proxy Server URI is invalid - make sure that either both proxy host "
            "and port are specified or neither."));
    return FALSE;
  }
begin_req_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
        ("Could not begin request: %d", res));
    return FALSE;
  }
}
コード例 #15
0
ファイル: ne_auth.c プロジェクト: elambert/honeycomb
static int ah_post_send(ne_request *req, void *cookie, const ne_status *status)
{
    auth_session *sess = cookie;
    struct auth_request *areq = ne_get_request_private(req, sess->spec->id);
    const char *auth_hdr, *auth_info_hdr;
    int ret = NE_OK;

    if (!areq) return NE_OK;

    auth_hdr = ne_get_response_header(req, sess->spec->resp_hdr);
    auth_info_hdr = ne_get_response_header(req, sess->spec->resp_info_hdr);

    if (sess->context == AUTH_CONNECT && status->code == 401 && !auth_hdr) {
        /* Some broken proxies issue a 401 as a proxy auth challenge
         * to a CONNECT request; handle this here. */
        auth_hdr = ne_get_response_header(req, "WWW-Authenticate");
        auth_info_hdr = NULL;
    }

#ifdef HAVE_GSSAPI
    /* whatever happens: forget the GSSAPI token cached thus far */
    if (sess->gssapi_token) {
        ne_free(sess->gssapi_token);
        sess->gssapi_token = NULL;
    }
#endif

    NE_DEBUG(NE_DBG_HTTPAUTH, 
	     "ah_post_send (#%d), code is %d (want %d), %s is %s\n",
	     sess->attempt, status->code, sess->spec->status_code, 
	     sess->spec->resp_hdr, auth_hdr ? auth_hdr : "(none)");
    if (auth_info_hdr && sess->scheme == auth_scheme_digest) {
        if (verify_digest_response(areq, sess, auth_info_hdr)) {
            NE_DEBUG(NE_DBG_HTTPAUTH, "Response authentication invalid.\n");
            ne_set_error(sess->sess, "%s", _(sess->spec->fail_msg));
            ret = NE_ERROR;
        }
    }
#ifdef HAVE_GSSAPI
    /* one must wonder... has Mr Brezak actually read RFC2617? */
    else if (sess->scheme == auth_scheme_gssapi 
             && (status->klass == 2 || status->klass == 3)
             && auth_hdr) {
        char *hdr = ne_strdup(auth_hdr);
        if (verify_negotiate_response(sess, hdr)) { 
            NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Mutual auth failed.\n");
            ret = NE_ERROR;
        }
        ne_free(hdr);
    }
#endif /* HAVE_GSSAPI */
    else if ((status->code == sess->spec->status_code ||
              (status->code == 401 && sess->context == AUTH_CONNECT)) &&
	       auth_hdr) {
        /* note above: allow a 401 in response to a CONNECT request
         * from a proxy since some buggy proxies send that. */
	NE_DEBUG(NE_DBG_HTTPAUTH, "Got challenge (code %d).\n", status->code);
	if (!auth_challenge(sess, auth_hdr)) {
	    ret = NE_RETRY;
	} else {
	    clean_session(sess);
	    ret = sess->spec->fail_code;
	}
    }
#ifdef HAVE_SSPI
    else if (sess->sspi_context) {
        ne_sspi_clear_context(sess->sspi_context);
    }
#endif

    return ret;
}
コード例 #16
0
ファイル: httpbf.c プロジェクト: VineyardVolunteer/client
/*
 * perform one transfer of one block.
 * returns HBF_TRANSFER_SUCCESS if the transfer of this block was a success
 * returns HBF_SUCCESS if the server aknoweldge that he received all the blocks
 */
static int _hbf_dav_request(hbf_transfer_t *transfer, ne_request *req, int fd, hbf_block_t *blk ) {
    Hbf_State state = HBF_TRANSFER_SUCCESS;
    int res;
    const ne_status *req_status = NULL;
    const char *etag = NULL;

    (void) transfer;

    if( ! (blk && req) ) return HBF_PARAM_FAIL;

    ne_set_request_body_fd(req, fd, blk->start, blk->size);
    DEBUG_HBF("Block: %d , Start: %" PRId64 " and Size: %" PRId64 "", blk->seq_number, blk->start, blk->size );
    res = ne_request_dispatch(req);

    req_status = ne_get_status( req );

    switch(res) {
    case NE_OK:
        blk->state = HBF_TRANSFER_FAILED;
        state = HBF_FAIL;
        etag = 0;
        if( req_status->klass == 2 ) {
            state = HBF_TRANSFER_SUCCESS;
            blk->state = HBF_TRANSFER_SUCCESS;
            etag = ne_get_response_header(req, "ETag");
            if (etag && etag[0]) {
                /* When there is an etag, it means the transfer was complete */
                state = HBF_SUCCESS;

                if( etag[0] == '"' && etag[ strlen(etag)-1] == '"') {
                     int len = strlen( etag )-2;
                     blk->etag = malloc( len+1 );
                     strncpy( blk->etag, etag+1, len );
                     blk->etag[len] = '\0';
                } else {
                    blk->etag = strdup( etag );
                }
            } else {
                /* DEBUG_HBF("OOOOOOOO No etag returned!"); */
            }

            /* check if the server was able to set the mtime already. */
            etag = ne_get_response_header(req, "X-OC-MTime");
            if( etag && strcmp(etag, "accepted") == 0 ) {
                /* the server acknowledged that the mtime was set. */
                transfer->modtime_accepted = 1;
            }

            etag = ne_get_response_header(req, "OC-FileID");
            if( etag ) {
                transfer->file_id = strdup( etag );
            }
        }
        break;
    case NE_AUTH:
            state = HBF_AUTH_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
            break;
        case NE_PROXYAUTH:
            state = HBF_PROXY_AUTH_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
        break;
        case NE_CONNECT:
            state = HBF_CONNECT_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
        break;
        case NE_TIMEOUT:
            state = HBF_TIMEOUT_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
            break;
        case NE_ERROR:
            state = HBF_FAIL;
            blk->state = HBF_TRANSFER_FAILED;
            break;
    }

    blk->http_result_code = req_status->code;
    if( req_status->reason_phrase ) {
        blk->http_error_msg = strdup(req_status->reason_phrase);
    }

    return state;
}
コード例 #17
0
ファイル: ne_compress.c プロジェクト: Distrotech/gnome-vfs
/* Callback which is passed blocks of the response body. */
static int gz_reader(void *ud, const char *buf, size_t len)
{
    ne_decompress *ctx = ud;
    const char *zbuf;
    size_t count;
    const char *hdr;

    if (len == 0) {
        /* End of response: */
        switch (ctx->state) {
        case NE_Z_BEFORE_DATA:
            hdr = ne_get_response_header(ctx->request, "Content-Encoding");
            if (hdr && strcasecmp(hdr, "gzip") == 0) {
                /* response was truncated: return error. */
                break;
            }
            /* else, fall through */
        case NE_Z_FINISHED: /* complete gzip response */
        case NE_Z_PASSTHROUGH: /* complete uncompressed response */
            return ctx->reader(ctx->userdata, buf, 0);
        default:
            /* invalid state: truncated response. */
            break;
        }
	/* else: truncated response, fail. */
	ne_set_error(ctx->session, "Compressed response was truncated");
	return NE_ERROR;
    }        

    switch (ctx->state) {
    case NE_Z_PASSTHROUGH:
	/* move along there. */
	return ctx->reader(ctx->userdata, buf, len);

    case NE_Z_FINISHED:
	/* Could argue for tolerance, and ignoring trailing content;
	 * but it could mean something more serious. */
	if (len > 0) {
	    ne_set_error(ctx->session,
			 "Unexpected content received after compressed stream");
            return NE_ERROR;
	}
        break;

    case NE_Z_BEFORE_DATA:
	/* work out whether this is a compressed response or not. */
        hdr = ne_get_response_header(ctx->request, "Content-Encoding");
        if (hdr && strcasecmp(hdr, "gzip") == 0) {
            int ret;
	    NE_DEBUG(NE_DBG_HTTP, "compress: got gzipped stream.\n");

            /* inflateInit2() works here where inflateInit() doesn't. */
            ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
            if (ret != Z_OK) {
                set_zlib_error(ctx, _("Could not initialize zlib"), ret);
                return -1;
            }
	    ctx->zstrinit = 1;

	} else {
	    /* No Content-Encoding header: pass it on.  TODO: we could
	     * hack it and register the real callback now. But that
	     * would require add_resp_body_rdr to have defined
	     * ordering semantics etc etc */
	    ctx->state = NE_Z_PASSTHROUGH;
	    return ctx->reader(ctx->userdata, buf, len);
	}

	ctx->state = NE_Z_IN_HEADER;
	/* FALLTHROUGH */

    case NE_Z_IN_HEADER:
	/* copy as many bytes as possible into the buffer. */
	if (len + ctx->hdrcount > 10) {
	    count = 10 - ctx->hdrcount;
	} else {
	    count = len;
	}
	memcpy(ctx->header + ctx->hdrcount, buf, count);
	ctx->hdrcount += count;
	/* have we got the full header yet? */
	if (ctx->hdrcount != 10) {
	    return 0;
	}

	buf += count;
	len -= count;

	switch (parse_header(ctx)) {
	case HDR_EXTENDED:
	    if (len == 0)
		return 0;
	    break;
        case HDR_ERROR:
            return NE_ERROR;
	case HDR_DONE:
	    if (len > 0) {
		return do_inflate(ctx, buf, len);
	    }
            break;
	}

	/* FALLTHROUGH */

    case NE_Z_POST_HEADER:
	/* eating the filename string. */
	zbuf = memchr(buf, '\0', len);
	if (zbuf == NULL) {
	    /* not found it yet. */
	    return 0;
	}

	NE_DEBUG(NE_DBG_HTTP,
		 "compresss: skipped %" NE_FMT_SIZE_T " header bytes.\n", 
		 zbuf - buf);
	/* found end of string. */
	len -= (1 + zbuf - buf);
	buf = zbuf + 1;
	ctx->state = NE_Z_INFLATING;
	if (len == 0) {
	    /* end of string was at end of buffer. */
	    return 0;
	}

	/* FALLTHROUGH */

    case NE_Z_INFLATING:
	return do_inflate(ctx, buf, len);

    case NE_Z_AFTER_DATA:
	return process_footer(ctx, (unsigned char *)buf, len);
    }

    return 0;
}
コード例 #18
0
ファイル: csync_owncloud.c プロジェクト: liusijiang/mirall
/*
 * This hook is called for with the response of a request. Here its checked
 * if a Set-Cookie header is there for the PHPSESSID. The key is stored into
 * the webdav session to be added to subsequent requests.
 */
static void post_request_hook(ne_request *req, void *userdata, const ne_status *status)
{
    const char *set_cookie_header = NULL;
    const char *sc  = NULL;
    char *key = NULL;

    (void) userdata;

    if (dav_session.session_key)
        return; /* We already have a session cookie, and we should ignore other ones */

    if(!(status && req)) return;
    if( status->klass == 2 || status->code == 401 ) {
        /* successful request */
        set_cookie_header =  ne_get_response_header( req, "Set-Cookie" );
        if( set_cookie_header ) {
            DEBUG_WEBDAV(" Set-Cookie found: %s", set_cookie_header);
            /* try to find a ', ' sequence which is the separator of neon if multiple Set-Cookie
             * headers are there.
             * The following code parses a string like this:
             * Set-Cookie: 50ace6bd8a669=p537brtt048jh8srlp2tuep7em95nh9u98mj992fbqc47d1aecp1;
             */
            sc = set_cookie_header;
            while(sc) {
                const char *sc_val = sc;
                const char *sc_end = sc_val;
                int cnt = 0;
                int len = strlen(sc_val); /* The length of the rest of the header string. */

                while( cnt < len && *sc_end != ';' && *sc_end != ',') {
                    cnt++;
                    sc_end++;
                }
                if( cnt == len ) {
                    /* exit: We are at the end. */
                    sc = NULL;
                } else if( *sc_end == ';' ) {
                    /* We are at the end of the session key. */
                    int keylen = sc_end-sc_val;
                    if( key ) {
                        int oldlen = strlen(key);
                        key = c_realloc(key, oldlen + 2 + keylen+1);
                        strcpy(key + oldlen, "; ");
                        strncpy(key + oldlen + 2, sc_val, keylen);
                        key[oldlen + 2 + keylen] = '\0';
                    } else {
                        key = c_malloc(keylen+1);
                        strncpy( key, sc_val, keylen );
                        key[keylen] = '\0';
                    }

                    /* now search for a ',' to find a potential other header entry */
                    while(cnt < len && *sc_end != ',') {
                        cnt++;
                        sc_end++;
                    }
                    if( cnt < len )
                        sc = sc_end+2; /* mind the space after the comma */
                    else
                        sc = NULL;
                } else if( *sc_end == ',' ) {
                    /* A new entry is to check. */
                    if( *(sc_end + 1) == ' ') {
                        sc = sc_end+2;
                    } else {
                        /* error condition */
                        sc = NULL;
                    }
                }
            }
        }
    } else {
        DEBUG_WEBDAV("Request failed, don't take session header.");
    }
    if( key ) {
        DEBUG_WEBDAV("----> Session-key: %s", key);
        SAFE_FREE(dav_session.session_key);
        dav_session.session_key = key;
    }
}
コード例 #19
0
ファイル: csync_owncloud.c プロジェクト: liusijiang/mirall
/*
 * fetches a resource list from the WebDAV server. This is equivalent to list dir.
 */
static struct listdir_context *fetch_resource_list(const char *uri, int depth)
{
    struct listdir_context *fetchCtx;
    int ret = 0;
    ne_propfind_handler *hdl = NULL;
    ne_request *request = NULL;
    const char *content_type = NULL;
    char *curi = NULL;
    const ne_status *req_status = NULL;

    curi = _cleanPath( uri );

    /* The old legacy one-level PROPFIND cache. Also gets filled
       by the recursive cache if 'infinity' did not suceed. */
    if (propfind_cache) {
        if (c_streq(curi, propfind_cache->target)) {
            DEBUG_WEBDAV("fetch_resource_list Using simple PROPFIND cache %s", curi);
            propfind_cache->ref++;
            SAFE_FREE(curi);
            return propfind_cache;
        }
    }

    fetchCtx = c_malloc( sizeof( struct listdir_context ));
    if (!fetchCtx) {
        errno = ENOMEM;
        SAFE_FREE(curi);
        return NULL;
    }
    fetchCtx->list = NULL;
    fetchCtx->target = curi;
    fetchCtx->currResource = NULL;
    fetchCtx->ref = 1;

    /* do a propfind request and parse the results in the results function, set as callback */
    hdl = ne_propfind_create(dav_session.ctx, curi, depth);

    if(hdl) {
        ret = ne_propfind_named(hdl, ls_props, results, fetchCtx);
        request = ne_propfind_get_request( hdl );
        req_status = ne_get_status( request );
    }

    if( ret == NE_OK ) {
        fetchCtx->currResource = fetchCtx->list;
        /* Check the request status. */
        if( req_status && req_status->klass != 2 ) {
            set_errno_from_http_errcode(req_status->code);
            DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
                         req_status->reason_phrase);
            ret = NE_CONNECT;
            set_error_message(req_status->reason_phrase);
            oc_notify_progress( uri, CSYNC_NOTIFY_ERROR,
                                req_status->code,
                                (intptr_t)(req_status->reason_phrase) );
        }
        DEBUG_WEBDAV("Simple propfind result code %d.", req_status->code);
    } else {
        if( ret == NE_ERROR && req_status->code == 404) {
            errno = ENOENT;
        } else {
            set_errno_from_neon_errcode(ret);
        }
    }

    if( ret == NE_OK ) {
        /* Check the content type. If the server has a problem, ie. database is gone or such,
         * the content type is not xml but a html error message. Stop on processing if it's
         * not XML.
         * FIXME: Generate user error message from the reply content.
         */
        content_type =  ne_get_response_header( request, "Content-Type" );
        if( !(content_type && c_streq(content_type, "application/xml; charset=utf-8") ) ) {
            DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
                         content_type ?  content_type: "<empty>");
            errno = ERRNO_WRONG_CONTENT;
            set_error_message("Server error: PROPFIND reply is not XML formatted!");
            ret = NE_CONNECT;
        }
    }

    if( ret != NE_OK ) {
        const char *err = NULL;
        set_errno_from_neon_errcode(ret);

        err = ne_get_error( dav_session.ctx );
        if(err) {
            set_error_message(err);
        }
        DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
    }

    if( hdl )
        ne_propfind_destroy(hdl);

    if( ret != NE_OK ) {
        free_fetchCtx(fetchCtx);
        return NULL;
    }

    free_fetchCtx(propfind_cache);
    propfind_cache = fetchCtx;
    propfind_cache->ref++;
    return fetchCtx;
}
コード例 #20
0
ファイル: csync_owncloud.c プロジェクト: gco/csync
static int fetch_resource_list( const char *uri,
                                int depth,
                                struct listdir_context *fetchCtx )
{
  int ret = 0;
  ne_propfind_handler *hdl = NULL;
  ne_request *request = NULL;
  const char *content_type = NULL;
  char *curi = NULL;
  const ne_status *req_status = NULL;

  curi = _cleanPath( uri );

  if (!fetchCtx) {
    errno = ENOMEM;
    SAFE_FREE(curi);
    return -1;
  }
  fetchCtx->list = NULL;
  fetchCtx->target = curi;
  fetchCtx->currResource = NULL;

  /* do a propfind request and parse the results in the results function, set as callback */
  hdl = ne_propfind_create(dav_session.ctx, curi, depth);

  if(hdl) {
    ret = ne_propfind_named(hdl, ls_props, results, fetchCtx);
    request = ne_propfind_get_request( hdl );
    req_status = ne_get_status( request );
  }

  if( ret == NE_OK ) {
    fetchCtx->currResource = fetchCtx->list;
    /* Check the request status. */
    if( req_status && req_status->klass != 2 ) {
      set_errno_from_http_errcode(req_status->code);
      DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
                   req_status->reason_phrase);
      ret = NE_CONNECT;
      set_error_message(req_status->reason_phrase);
    }
    DEBUG_WEBDAV("Simple propfind result code %d.", req_status ? req_status->code : -1);
  } else {
    if( ret == NE_ERROR && req_status->code == 404) {
      errno = ENOENT;
    } else {
      set_errno_from_neon_errcode(ret);
    }
  }

  if( ret == NE_OK ) {
    /* Check the content type. If the server has a problem, ie. database is gone or such,
        * the content type is not xml but a html error message. Stop on processing if it's
        * not XML.
        * FIXME: Generate user error message from the reply content.
        */
    content_type =  ne_get_response_header( request, "Content-Type" );
    if( !(content_type && c_streq(content_type, "application/xml; charset=utf-8") ) ) {
      DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
                   content_type ?  content_type: "<empty>");
      errno = ERRNO_WRONG_CONTENT;
      set_error_message("Server error: PROPFIND reply is not XML formatted!");
      ret = NE_CONNECT;
    }
  }
#ifndef NDEBUG
  if( ret != NE_OK ) {
    const char *err = ne_get_error(dav_session.ctx);
    DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
  }
#endif /* NDEBUG */

  if (hdl != NULL) {
    ne_propfind_destroy(hdl);
  }

#ifndef NDEBUG
  if (ret == NE_REDIRECT) {
    const ne_uri *redir_ne_uri = ne_redirect_location(dav_session.ctx);
    if (redir_ne_uri) {
      char *redir_uri = ne_uri_unparse(redir_ne_uri);
      DEBUG_WEBDAV("Permanently moved to %s", redir_uri);
    }
  }
#endif /* NDEBUG */

  if( ret != NE_OK ) {
    free_fetchCtx(fetchCtx);
    return -1;
  }

  return 0;
}
コード例 #21
0
void fetch_resource_list_recursive(const char *uri, const char *curi)
{
    int ret = 0;
    ne_propfind_handler *hdl = NULL;
    ne_request *request = NULL;
    const char *content_type = NULL;
    const ne_status *req_status = NULL;
    int depth = NE_DEPTH_INFINITE;

    DEBUG_WEBDAV("fetch_resource_list_recursive Starting recursive propfind %s %s", uri, curi);

    /* do a propfind request and parse the results in the results function, set as callback */
    hdl = ne_propfind_create(dav_session.ctx, curi, depth);

    if(hdl) {
        ret = ne_propfind_named(hdl, ls_props, propfind_results_recursive, (void*)curi);
        request = ne_propfind_get_request( hdl );
        req_status = ne_get_status( request );
    }

    if( ret == NE_OK ) {
        /* Check the request status. */
        if( req_status && req_status->klass != 2 ) {
            set_errno_from_http_errcode(req_status->code);
            DEBUG_WEBDAV("ERROR: Request failed: status %d (%s)", req_status->code,
                         req_status->reason_phrase);
            ret = NE_CONNECT;
            set_error_message(req_status->reason_phrase);
        }
        DEBUG_WEBDAV("Recursive propfind result code %d.", req_status ? req_status->code : 0);
    } else {
        if( ret == NE_ERROR && req_status->code == 404) {
            errno = ENOENT;
        } else {
            set_errno_from_neon_errcode(ret);
        }
    }

    if( ret == NE_OK ) {
        /* Check the content type. If the server has a problem, ie. database is gone or such,
         * the content type is not xml but a html error message. Stop on processing if it's
         * not XML.
         * FIXME: Generate user error message from the reply content.
         */
        content_type =  ne_get_response_header( request, "Content-Type" );
        if( !(content_type && c_streq(content_type, "application/xml; charset=utf-8") ) ) {
            DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
                         content_type ?  content_type: "<empty>");
            errno = ERRNO_WRONG_CONTENT;
            set_error_message("Server error: PROPFIND reply is not XML formatted!");
            ret = NE_CONNECT;
        }
    }

    if( ret != NE_OK ) {
        const char *err = NULL;

        err = ne_get_error( dav_session.ctx );
        DEBUG_WEBDAV("WRN: propfind named failed with %d, request error: %s", ret, err ? err : "<nil>");
    }

    if( hdl )
        ne_propfind_destroy(hdl);

    if( ret != NE_OK ) {
        return;
    }

    return;
}
コード例 #22
0
ファイル: csync_owncloud.c プロジェクト: Gnostech/mirall
static const char* owncloud_get_etag( const char *path )
{
    ne_request *req    = NULL;
    const char *header = NULL;
    char *uri          = _cleanPath(path);
    char *cbuf   = NULL;
    csync_vio_file_stat_t *fs = NULL;
    bool doHeadRequest = false;

    if (_id_cache.uri && c_streq(path, _id_cache.uri)) {
        header = _id_cache.id;
    }

    doHeadRequest= false; /* ownCloud server doesn't have good support for HEAD yet */

    if( !header && doHeadRequest ) {
        int neon_stat;
        /* Perform an HEAD request to the resource. HEAD delivers the
         * ETag header back. */
        req = ne_request_create(dav_session.ctx, "HEAD", uri);
        neon_stat = ne_request_dispatch(req);
        set_errno_from_neon_errcode( neon_stat );

        header = ne_get_response_header(req, "etag");
    }
    /* If the request went wrong or the server did not respond correctly
     * (that can happen for collections) a stat call is done which translates
     * into a PROPFIND request.
     */
    if( ! header ) {
        /* ... and do a stat call. */
        fs = csync_vio_file_stat_new();
        if(fs == NULL) {
            DEBUG_WEBDAV( "owncloud_get_etag: memory fault.");
            errno = ENOMEM;
            return NULL;
        }
        if( owncloud_stat( path, fs ) == 0 ) {
            header = fs->etag;
        }
    }

    /* In case the result is surrounded by "" cut them away. */
    if( header ) {
        cbuf = csync_normalize_etag(header);
    }

    /* fix server problem: If we end up with an empty string, set something strange... */
    if( c_streq(cbuf, "") || c_streq(cbuf, "\"\"") ) {
        SAFE_FREE(cbuf);
        cbuf = c_strdup("empty_etag");
    }

    DEBUG_WEBDAV("Get file ID for %s: %s", path, cbuf ? cbuf:"<null>");
    if( fs ) csync_vio_file_stat_destroy(fs);
    if( req ) ne_request_destroy(req);
    SAFE_FREE(uri);


    return cbuf;
}
コード例 #23
0
/* create a socket for connecting to remote server */
static gboolean
gst_neonhttp_src_start (GstBaseSrc * bsrc)
{
    GstNeonhttpSrc *src = GST_NEONHTTP_SRC (bsrc);
    const gchar *content_length;
    gint res;

#ifndef GST_DISABLE_GST_DEBUG
    if (src->neon_http_debug)
        ne_debug_init (stderr, NE_DBG_HTTP);
#endif

    ne_oom_callback (oom_callback);

    res = ne_sock_init ();
    if (res != 0)
        goto init_failed;

    res = gst_neonhttp_src_send_request_and_redirect (src,
            &src->session, &src->request, 0, src->automatic_redirect);

    if (res != NE_OK || !src->session) {
        if (res == HTTP_SOCKET_ERROR) {
            goto socket_error;
        } else if (res == HTTP_REQUEST_WRONG_PROXY) {
            goto wrong_proxy;
        } else {
            goto begin_req_failed;
        }
    }

    content_length = ne_get_response_header (src->request, "Content-Length");

    if (content_length)
        src->content_size = g_ascii_strtoull (content_length, NULL, 10);
    else
        src->content_size = -1;

    if (TRUE) {
        /* Icecast stuff */
        const gchar *str_value;
        GstTagList *tags;
        gchar *iradio_name;
        gchar *iradio_url;
        gchar *iradio_genre;
        gint icy_metaint;

        tags = gst_tag_list_new_empty ();

        str_value = ne_get_response_header (src->request, "icy-metaint");
        if (str_value) {
            if (sscanf (str_value, "%d", &icy_metaint) == 1) {
                GstCaps *icy_caps;

                icy_caps = gst_caps_new_simple ("application/x-icy",
                                                "metadata-interval", G_TYPE_INT, icy_metaint, NULL);
                gst_base_src_set_caps (GST_BASE_SRC (src), icy_caps);
            }
        }

        /* FIXME: send tags with name, genre, url */
        str_value = ne_get_response_header (src->request, "icy-name");
        if (str_value) {
            iradio_name = gst_neonhttp_src_unicodify (str_value);
            if (iradio_name) {
                gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_ORGANIZATION,
                                  iradio_name, NULL);
                g_free (iradio_name);
            }
        }
        str_value = ne_get_response_header (src->request, "icy-genre");
        if (str_value) {
            iradio_genre = gst_neonhttp_src_unicodify (str_value);
            if (iradio_genre) {
                gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_GENRE,
                                  iradio_genre, NULL);
                g_free (iradio_genre);
            }
        }
        str_value = ne_get_response_header (src->request, "icy-url");
        if (str_value) {
            iradio_url = gst_neonhttp_src_unicodify (str_value);
            if (iradio_url) {
                gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_LOCATION,
                                  iradio_url, NULL);
                g_free (iradio_url);
            }
        }
        if (!gst_tag_list_is_empty (tags)) {
            GST_DEBUG_OBJECT (src, "pushing tag list %" GST_PTR_FORMAT, tags);
            gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_tag (tags));
        } else {
            gst_tag_list_unref (tags);
        }
    }

    return TRUE;

    /* ERRORS */
init_failed:
    {
        GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
                           ("ne_sock_init() failed: %d", res));
        return FALSE;
    }
socket_error:
    {
        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
                           ("HTTP Request failed when opening socket: %d", res));
        return FALSE;
    }
wrong_proxy:
    {
        GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
                           ("Proxy Server URI is invalid - make sure that either both proxy host "
                            "and port are specified or neither."));
        return FALSE;
    }
begin_req_failed:
    {
        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
                           ("Could not begin request: %d", res));
        return FALSE;
    }
}
コード例 #24
0
/* Try to send the HTTP request to the Icecast server, and if possible deals with
 * all the probable redirections (HTTP status code == 3xx)
 */
static gint
gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
        ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir)
{
    ne_session *session = NULL;
    ne_request *request = NULL;
    gchar **c;
    gint res;
    gint http_status = 0;
    guint request_count = 0;

    do {
        if (src->proxy.host && src->proxy.port) {
            session =
                ne_session_create (src->uri.scheme, src->uri.host, src->uri.port);
            ne_session_proxy (session, src->proxy.host, src->proxy.port);
        } else if (src->proxy.host || src->proxy.port) {
            /* both proxy host and port must be specified or none */
            return HTTP_REQUEST_WRONG_PROXY;
        } else {
            session =
                ne_session_create (src->uri.scheme, src->uri.host, src->uri.port);
        }

        if (src->connect_timeout > 0) {
            ne_set_connect_timeout (session, src->connect_timeout);
        }

        if (src->read_timeout > 0) {
            ne_set_read_timeout (session, src->read_timeout);
        }

        ne_set_session_flag (session, NE_SESSFLAG_ICYPROTO, 1);
        ne_ssl_set_verify (session, ssl_verify_callback, src);

        request = ne_request_create (session, "GET", src->query_string);

        if (src->user_agent) {
            ne_add_request_header (request, "User-Agent", src->user_agent);
        }

        for (c = src->cookies; c != NULL && *c != NULL; ++c) {
            GST_INFO ("Adding header Cookie : %s", *c);
            ne_add_request_header (request, "Cookies", *c);
        }

        if (src->iradio_mode)
            ne_add_request_header (request, "icy-metadata", "1");

        if (offset > 0) {
            ne_print_request_header (request, "Range",
                                     "bytes=%" G_GINT64_FORMAT "-", offset);
        }

        res = ne_begin_request (request);

        if (res == NE_OK) {
            /* When the HTTP status code is 3xx, it is not the SHOUTcast streaming content yet;
             * Reload the HTTP request with a new URI value */
            http_status = ne_get_status (request)->code;
            if (STATUS_IS_REDIRECTION (http_status) && do_redir) {
                const gchar *redir;

                /* the new URI value to go when redirecting can be found on the 'Location' HTTP header */
                redir = ne_get_response_header (request, "Location");
                if (redir != NULL) {
                    ne_uri_free (&src->uri);
                    gst_neonhttp_src_set_location (src, redir, NULL);
                    GST_LOG_OBJECT (src, "Got HTTP Status Code %d", http_status);
                    GST_LOG_OBJECT (src, "Using 'Location' header [%s]", src->uri.host);
                }
            }
        }

        if ((res != NE_OK) ||
                (offset == 0 && http_status != 200) ||
                (offset > 0 && http_status != 206 &&
                 !STATUS_IS_REDIRECTION (http_status))) {
            ne_request_destroy (request);
            request = NULL;
            ne_close_connection (session);
            ne_session_destroy (session);
            session = NULL;
            if (offset > 0 && http_status != 206 &&
                    !STATUS_IS_REDIRECTION (http_status)) {
                src->seekable = FALSE;
            }
        }

        /* if - NE_OK */
        if (STATUS_IS_REDIRECTION (http_status) && do_redir) {
            ++request_count;
            GST_LOG_OBJECT (src, "redirect request_count is now %d", request_count);
            if (request_count < MAX_HTTP_REDIRECTS_NUMBER && do_redir) {
                GST_INFO_OBJECT (src, "Redirecting to %s", src->uri.host);
            } else {
                GST_WARNING_OBJECT (src, "Will not redirect, try again with a "
                                    "different URI or redirect location %s", src->uri.host);
            }
            /* FIXME: when not redirecting automatically, shouldn't we post a
             * redirect element message on the bus? */
        }
        /* do the redirect, go back to send another HTTP request now using the 'Location' */
    } while (do_redir && (request_count < MAX_HTTP_REDIRECTS_NUMBER)
             && STATUS_IS_REDIRECTION (http_status));

    if (session) {
        *ses = session;
        *req = request;
    }

    return res;
}