static void *fetch_rsrc_setup(struct fetch *parent_fetch, nsurl *url,
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
		 const struct fetch_multipart_data *post_multipart,
		 const char **headers)
{
	struct fetch_rsrc_context *ctx;
	ctx = (struct fetch_rsrc_context *)calloc(1, sizeof(*ctx));
	
	if (ctx == NULL)
		return NULL;
		
	ctx->parent_fetch = parent_fetch;
	/* TODO: keep as nsurl to avoid copy */
	ctx->url = (char *)malloc(nsurl_length(url) + 1);
	
	if (ctx->url == NULL) {
		free(ctx);
		return NULL;
	}
	memcpy(ctx->url, nsurl_access(url), nsurl_length(url) + 1);

	RING_INSERT(ring, ctx);
	
	return ctx;
}
Exemple #2
0
/**
 * Dispatch a single job
 */
static bool fetch_dispatch_job(struct fetch *fetch)
{
	RING_REMOVE(queue_ring, fetch);
#ifdef DEBUG_FETCH_VERBOSE
	LOG(("Attempting to start fetch %p, fetcher %p, url %s", fetch,
	     fetch->fetcher_handle, nsurl_access(fetch->url)));
#endif
	if (!fetch->ops->start_fetch(fetch->fetcher_handle)) {
		RING_INSERT(queue_ring, fetch); /* Put it back on the end of the queue */
		return false;
	} else {
		RING_INSERT(fetch_ring, fetch);
		fetch->fetch_is_active = true;
		return true;
	}
}
Exemple #3
0
void
monkey_register_handler(const char *cmd, handle_command_fn fn)
{
  monkey_cmdhandler_t *ret = calloc(sizeof(*ret), 1);
  if (ret == NULL)
    die("Unable to allocate handler");
  ret->cmd = strdup(cmd);
  ret->fn = fn;
  RING_INSERT(handler_ring, ret);
}
Exemple #4
0
/* See hlcache.h for documentation */
nserror hlcache_handle_retrieve(nsurl *url, uint32_t flags,
		nsurl *referer, llcache_post_data *post,
		hlcache_handle_callback cb, void *pw,
		hlcache_child_context *child,
		content_type accepted_types, hlcache_handle **result)
{
	hlcache_retrieval_ctx *ctx;
	nserror error;

	assert(cb != NULL);

	ctx = calloc(1, sizeof(hlcache_retrieval_ctx));
	if (ctx == NULL)
		return NSERROR_NOMEM;

	ctx->handle = calloc(1, sizeof(hlcache_handle));
	if (ctx->handle == NULL) {
		free(ctx);
		return NSERROR_NOMEM;
	}

	if (child != NULL) {
		if (child->charset != NULL) {
			ctx->child.charset = strdup(child->charset);
			if (ctx->child.charset == NULL) {
				free(ctx->handle);
				free(ctx);
				return NSERROR_NOMEM;
			}
		}
		ctx->child.quirks = child->quirks;
	}

	ctx->flags = flags;
	ctx->accepted_types = accepted_types;

	ctx->handle->cb = cb;
	ctx->handle->pw = pw;

	error = llcache_handle_retrieve(url, flags, referer, post,
			hlcache_llcache_callback, ctx,
			&ctx->llcache);
	if (error != NSERROR_OK) {
		free((char *) ctx->child.charset);
		free(ctx->handle);
		free(ctx);
		return error;
	}

	RING_INSERT(hlcache->retrieval_ctx_ring, ctx);

	*result = ctx->handle;

	return NSERROR_OK;
}
Exemple #5
0
nserror
monkey_register_handler(const char *cmd, handle_command_fn fn)
{
  monkey_cmdhandler_t *ret = calloc(sizeof(*ret), 1);
  if (ret == NULL) {
    LOG("Unable to allocate handler");
    return NSERROR_NOMEM;
  }
  ret->cmd = strdup(cmd);
  ret->fn = fn;
  RING_INSERT(handler_ring, ret);
  return NSERROR_OK;
}
Exemple #6
0
void gui_401login_open(const char *url, const char *realm,
                       nserror (*cb)(bool proceed, void *pw), void *cbpw)
{
  monkey401_t *m4t = calloc(sizeof(*m4t), 1);
  if (m4t == NULL)
    cb(false, cbpw);
  m4t->cb = cb;
  m4t->pw = cbpw;
  m4t->num = m4_ctr++;
  
  RING_INSERT(m4_ring, m4t);
  
  fprintf(stdout, "401LOGIN OPEN M4 %u URL %s REALM %s\n",
          m4t->num, url, realm);
}
Exemple #7
0
/**
 * Cache a CURL handle for the provided host (if wanted)
 */
static void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
{
#if LIBCURL_VERSION_NUM >= 0x071e00
	/* 7.30.0 or later has its own connection caching; suppress ours */
	curl_easy_cleanup(handle);
	return;
#else
	struct cache_handle *h = 0;
	int c;
	RING_FINDBYLWCHOST(curl_handle_ring, h, host);
	if (h) {
		/* Already have a handle cached for this hostname */
		curl_easy_cleanup(handle);
		return;
	}
	/* We do not have a handle cached, first up determine if the cache is full */
	RING_GETSIZE(struct cache_handle, curl_handle_ring, c);
	if (c >= nsoption_int(max_cached_fetch_handles)) {
		/* Cache is full, so, we rotate the ring by one and
		 * replace the oldest handle with this one. We do this
		 * without freeing/allocating memory (except the
		 * hostname) and without removing the entry from the
		 * ring and then re-inserting it, in order to be as
		 * efficient as we can.
		 */
		if (curl_handle_ring != NULL) {
			h = curl_handle_ring;
			curl_handle_ring = h->r_next;
			curl_easy_cleanup(h->handle);
			h->handle = handle;
			lwc_string_unref(h->host);
			h->host = lwc_string_ref(host);
		} else {
			/* Actually, we don't want to cache any handles */
			curl_easy_cleanup(handle);
		}

		return;
	}
	/* The table isn't full yet, so make a shiny new handle to add to the ring */
	h = (struct cache_handle*)malloc(sizeof(struct cache_handle));
	h->handle = handle;
	h->host = lwc_string_ref(host);
	RING_INSERT(curl_handle_ring, h);
#endif
}
Exemple #8
0
/** callback to set up a resource fetch context. */
static void *
fetch_resource_setup(struct fetch *fetchh,
		 nsurl *url,
		 bool only_2xx,
		 bool downgrade_tls,
		 const char *post_urlenc,
		 const struct fetch_multipart_data *post_multipart,
		 const char **headers)
{
	struct fetch_resource_context *ctx;
	lwc_string *path;

	ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL)
		return NULL;

	ctx->handler = fetch_resource_notfound_handler;

	if ((path = nsurl_get_component(url, NSURL_PATH)) != NULL) {
		uint32_t i;
		bool match;

		/* Ensure requested path is valid */
		for (i = 0; i < fetch_resource_path_count; i++) {
			if (lwc_string_isequal(path, 
					fetch_resource_map[i].path, 
					&match) == lwc_error_ok && match) {
				ctx->redirect_url = 
					nsurl_ref(fetch_resource_map[i].url);
				ctx->handler =
					fetch_resource_redirect_handler;
				break;
			}
		}

		lwc_string_unref(path);
	}

	ctx->url = nsurl_ref(url);

	ctx->fetchh = fetchh;

	RING_INSERT(ring, ctx);

	return ctx;
}
Exemple #9
0
nserror
gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs, 
                unsigned long num, nserror (*cb)(bool proceed, void *pw),
                void *cbpw)
{
  monkey_cert_t *m4t = calloc(sizeof(*m4t), 1);
  if (m4t == NULL) {
    return NSERROR_NOMEM;
  }
  m4t->cb = cb;
  m4t->pw = cbpw;
  m4t->num = cert_ctr++;
  
  RING_INSERT(cert_ring, m4t);
  
  fprintf(stdout, "SSLCERT VERIFY CERT %u URL %s\n",
          m4t->num, nsurl_access(url));

  return NSERROR_OK;
}
Exemple #10
0
/** callback to set up a about fetch context. */
static void *
fetch_about_setup(struct fetch *fetchh,
		 nsurl *url,
		 bool only_2xx,
		 bool downgrade_tls,
		 const char *post_urlenc,
		 const struct fetch_multipart_data *post_multipart,
		 const char **headers)
{
	struct fetch_about_context *ctx;
	unsigned int handler_loop;
	lwc_string *path;
	bool match;

	ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL)
		return NULL;

	path = nsurl_get_component(url, NSURL_PATH);

	for (handler_loop = 0; 
	     handler_loop < about_handler_list_len; 
	     handler_loop++) {
		ctx->handler = about_handler_list[handler_loop].handler;
		if (lwc_string_isequal(path, 
				       about_handler_list[handler_loop].lname, 
				       &match) == lwc_error_ok && match) {
			break;
		}		
	}

	if (path != NULL)
		lwc_string_unref(path);

	ctx->fetchh = fetchh;
	ctx->url = nsurl_ref(url);

	RING_INSERT(ring, ctx);

	return ctx;
}
Exemple #11
0
/** callback to set up a resource fetch context. */
static void *
fetch_javascript_setup(struct fetch *fetchh,
		 nsurl *url,
		 bool only_2xx,
		 bool downgrade_tls,
		 const char *post_urlenc,
		 const struct fetch_multipart_data *post_multipart,
		 const char **headers)
{
	struct fetch_javascript_context *ctx;

	ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL)
		return NULL;

	ctx->url = nsurl_ref(url);

	ctx->fetchh = fetchh;

	RING_INSERT(ring, ctx);

	return ctx;
}
Exemple #12
0
/* exported interface documented in content/fetch.h */
struct fetch * fetch_start(nsurl *url, nsurl *referer,
			   fetch_callback callback,
			   void *p, bool only_2xx, const char *post_urlenc,
			   const struct fetch_multipart_data *post_multipart,
			   bool verifiable, bool downgrade_tls,
			   const char *headers[])
{
	struct fetch *fetch;
	scheme_fetcher *fetcher = fetchers;
	lwc_string *scheme;
	bool match;

	fetch = malloc(sizeof (*fetch));
	if (fetch == NULL)
		return NULL;

	/* The URL we're fetching must have a scheme */
	scheme = nsurl_get_component(url, NSURL_SCHEME);
	assert(scheme != NULL);

#ifdef DEBUG_FETCH_VERBOSE
	LOG(("fetch %p, url '%s'", fetch, nsurl_access(url)));
#endif

	/* construct a new fetch structure */
	fetch->callback = callback;
	fetch->url = nsurl_ref(url);
	fetch->verifiable = verifiable;
	fetch->p = p;
	fetch->http_code = 0;
	fetch->r_prev = NULL;
	fetch->r_next = NULL;
	fetch->referer = NULL;
	fetch->send_referer = false;
	fetch->fetcher_handle = NULL;
	fetch->ops = NULL;
	fetch->fetch_is_active = false;
	fetch->host = nsurl_get_component(url, NSURL_HOST);

	if (referer != NULL) {
		lwc_string *ref_scheme;
		fetch->referer = nsurl_ref(referer);

		ref_scheme = nsurl_get_component(referer, NSURL_SCHEME);
		/* Not a problem if referer has no scheme */

		/* Determine whether to send the Referer header */
		if (nsoption_bool(send_referer) && ref_scheme != NULL) {
			/* User permits us to send the header
			 * Only send it if:
			 *    1) The fetch and referer schemes match
			 * or 2) The fetch is https and the referer is http
			 *
			 * This ensures that referer information is only sent
			 * across schemes in the special case of an https
			 * request from a page served over http. The inverse
			 * (https -> http) should not send the referer (15.1.3)
			 */
			bool match1;
			bool match2;
			if (lwc_string_isequal(scheme, ref_scheme,
					       &match) != lwc_error_ok) {
				match = false;
			}
			if (lwc_string_isequal(scheme, corestring_lwc_https,
					       &match1) != lwc_error_ok) {
				match1 = false;
			}
			if (lwc_string_isequal(ref_scheme, corestring_lwc_http,
					       &match2) != lwc_error_ok) {
				match2= false;
			}
			if (match == true || (match1 == true && match2 == true))
				fetch->send_referer = true;
		}
		if (ref_scheme != NULL)
			lwc_string_unref(ref_scheme);
	}

	/* Pick the scheme ops */
	while (fetcher) {
		if ((lwc_string_isequal(fetcher->scheme_name, scheme,
					&match) == lwc_error_ok) && (match == true)) {
			fetch->ops = fetcher;
			break;
		}
		fetcher = fetcher->next_fetcher;
	}

	if (fetch->ops == NULL)
		goto failed;

	/* Got a scheme fetcher, try and set up the fetch */
	fetch->fetcher_handle = fetch->ops->setup_fetch(fetch, url,
							only_2xx, downgrade_tls,
							post_urlenc, post_multipart,
							headers);

	if (fetch->fetcher_handle == NULL)
		goto failed;

	/* Rah, got it, so ref the fetcher. */
	fetch_ref_fetcher(fetch->ops);

	/* these aren't needed past here */
	lwc_string_unref(scheme);

	/* Dump us in the queue and ask the queue to run. */
	RING_INSERT(queue_ring, fetch);
	fetch_dispatch_jobs();

	return fetch;

failed:
	lwc_string_unref(scheme);

	if (fetch->host != NULL)
		lwc_string_unref(fetch->host);
	if (fetch->url != NULL)
		nsurl_unref(fetch->url);
	if (fetch->referer != NULL)
		nsurl_unref(fetch->referer);

	free(fetch);

	return NULL;
}