Example #1
0
END_TEST


/**
 * url reference (copy) and unreference(free)
 */
START_TEST(nsurl_ref_test)
{
	nserror err;
	nsurl *res1;
	nsurl *res2;

	err = nsurl_create(base_str, &res1);

	/* result must be valid */
	ck_assert(err == NSERROR_OK);

	res2 = nsurl_ref(res1);

	ck_assert_str_eq(nsurl_access(res1), nsurl_access(res2));

	nsurl_unref(res2);

	nsurl_unref(res1);
}
Example #2
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;
}
Example #3
0
END_TEST

/**
 * check ref asserts on NULL parameter
 */
START_TEST(nsurl_api_assert_ref_test)
{
	nsurl_ref(NULL);
}
Example #4
0
bool content__add_rfc5988_link(struct content *c, 
		const struct content_rfc5988_link *link)
{
	struct content_rfc5988_link *newlink;	
	union content_msg_data msg_data;

	/* a link relation must be present for it to be a link */
	if (link->rel == NULL) {
		return false;
	}

	/* a link href must be present for it to be a link */
	if (link->href == NULL) {
		return false;
	}

	newlink = calloc(1, sizeof(struct content_rfc5988_link));
	if (newlink == NULL) {
		return false; 
	}

	/* copy values */
	newlink->rel = lwc_string_ref(link->rel);
	newlink->href = nsurl_ref(link->href);
	if (link->hreflang != NULL) {
		newlink->hreflang = lwc_string_ref(link->hreflang);
	}
	if (link->type != NULL) {
		newlink->type = lwc_string_ref(link->type);
	}
	if (link->media != NULL) {
		newlink->media = lwc_string_ref(link->media);
	}
	if (link->sizes != NULL) {
		newlink->sizes = lwc_string_ref(link->sizes);
	}

	/* add to metadata link to list */
	newlink->next = c->links;
	c->links = newlink;

	/* broadcast the data */
	msg_data.rfc5988_link = newlink;
	content_broadcast(c, CONTENT_MSG_LINK, msg_data);

	return true;
}
Example #5
0
/* Documented in local_history.h */
void browser_window_history_go(struct browser_window *bw,
		struct history_entry *entry, bool new_window)
{
	struct history *history;
	nsurl *url;
	struct history_entry *current;
	nserror error;

	assert(bw != NULL);
	history = bw->history;

	if (entry->page.frag_id) {
		error = nsurl_refragment(entry->page.url,
				entry->page.frag_id, &url);

		if (error != NSERROR_OK) {
			warn_user("NoMemory", 0);
			return;
		}
	} else {
		url = nsurl_ref(entry->page.url);
	}

	if (new_window) {
		current = history->current;
		history->current = entry;

		error = browser_window_create(BW_CREATE_CLONE,
				url, NULL, bw, NULL);
		history->current = current;
		if (error != NSERROR_OK) {
			nsurl_unref(url);
			return;
		}
	} else {
		history->current = entry;
		browser_window_navigate(bw, url, NULL,
				BW_NAVIGATE_NONE, NULL, NULL, NULL);
	}

	nsurl_unref(url);
}
Example #6
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;
}
Example #7
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;
}
Example #8
0
/**
 * Clone a history entry
 *
 * \param history opaque history structure, as returned by history_create()
 * \param entry   entry to clone
 * \return A cloned history entry or NULL on error
 */
static struct history_entry *
browser_window_history__clone_entry(struct history *history,
				    struct history_entry *entry)
{
	struct history_entry *child;
	struct history_entry *new_child;
	struct history_entry *prev = NULL;
	struct history_entry *new_entry;

	assert(entry->page.url);
	assert(entry->page.title);

	/* clone the entry */
	new_entry = malloc(sizeof *entry);
	if (!new_entry)
		return NULL;

	memcpy(new_entry, entry, sizeof *entry);
	new_entry->page.url = nsurl_ref(entry->page.url);
	if (entry->page.frag_id)
		new_entry->page.frag_id = lwc_string_ref(entry->page.frag_id);

	new_entry->page.title = strdup(entry->page.title);
	if (!new_entry->page.url || !new_entry->page.title ||
			((entry->page.frag_id) && (!new_entry->page.frag_id))) {
		nsurl_unref(new_entry->page.url);
		if (new_entry->page.frag_id)
			lwc_string_unref(new_entry->page.frag_id);
		free(new_entry->page.title);
		free(new_entry);
		return NULL;
	}

	/* update references */
	if (history->current == entry)
		history->current = new_entry;

	/* recurse for all children */
	for (child = new_entry->forward; child; child = child->next) {
		new_child = browser_window_history__clone_entry(history, child);
		if (new_child) {
			new_child->back = new_entry;
		} else {
			nsurl_unref(new_entry->page.url);
			if (new_entry->page.frag_id)
				lwc_string_unref(new_entry->page.frag_id);
			free(new_entry->page.title);
			free(new_entry);
			return NULL;
		}
		if (prev)
			prev->next = new_child;
		if (new_entry->forward == child)
			new_entry->forward = new_child;
		if (new_entry->forward_pref == child)
			new_entry->forward_pref = new_child;
		if (new_entry->forward_last == child)
			new_entry->forward_last = new_child;
		prev = new_child;
	}
	return new_entry;
}
Example #9
0
/**
 * Recursively redraw a history_entry.
 *
 * \param history history containing the entry
 * \param entry entry to render
 * \param x0 area top left x coordinate
 * \param y0 area top left y coordinate
 * \param x1 area bottom right x coordinate
 * \param y1 area bottom right y coordinate
 * \param x window x offset
 * \param y window y offset
 * \param clip clip redraw
 * \param ctx     current redraw context
 */
static bool
browser_window_history__redraw_entry(struct history *history,
		struct history_entry *entry,
		int x0, int y0, int x1, int y1,
		int x, int y, bool clip,
		const struct redraw_context *ctx)
{
	const struct plotter_table *plot = ctx->plot;
	size_t char_offset;
	int actual_x;
	struct history_entry *child;
	colour c = entry == history->current ?
			HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND;
	int tailsize = 5;
	int xoffset = x - x0;
	int yoffset = y - y0;
        plot_style_t pstyle_history_rect = { 
            .stroke_type = PLOT_OP_TYPE_SOLID,
            .stroke_colour = c,
            .stroke_width = entry == history->current ? 3 : 1,
        };
	plot_font_style_t fstyle = *plot_style_font;

	if (clip) {
		struct rect rect;
		rect.x0 = x0 + xoffset;
		rect.y0 = y0 + yoffset;
		rect.x1 = x1 + xoffset;
		rect.y1 = y1 + yoffset;
		if (!plot->clip(&rect)) {
			return false;
		}
	}

	/* Only attempt to plot bitmap if it is present */
	if (entry->bitmap != NULL) {
		plot->bitmap(entry->x + xoffset,
			     entry->y + yoffset,
			     WIDTH, HEIGHT,
			     entry->bitmap, 0xffffff, 0);
	}
	if (!plot->rectangle(entry->x - 1 + xoffset, 
                            entry->y - 1 + yoffset,
                            entry->x + xoffset + WIDTH, 
                            entry->y + yoffset + HEIGHT,
                            &pstyle_history_rect))
		return false;

	if (!nsfont.font_position_in_string(plot_style_font, entry->page.title,
			strlen(entry->page.title), WIDTH,
			&char_offset, &actual_x))
		return false;

	fstyle.background = HISTORY_COLOUR_BACKGROUND;
	fstyle.foreground = c;
	fstyle.weight = entry == history->current ? 900 : 400;

	if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset,
			entry->page.title, char_offset, &fstyle))
		return false;

	for (child = entry->forward; child; child = child->next) {
		if (!plot->line(entry->x + WIDTH + xoffset,
				entry->y + HEIGHT / 2 + yoffset,
		      	entry->x + WIDTH + tailsize + xoffset,
				entry->y + HEIGHT / 2 + yoffset, 
			       plot_style_stroke_history))
			return false;
		if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
			       entry->y + HEIGHT / 2 + yoffset,
			       child->x - tailsize +xoffset,
			       child->y + HEIGHT / 2 + yoffset,
			       plot_style_stroke_history))
			return false;
		if (!plot->line(child->x - tailsize + xoffset,
			       child->y + HEIGHT / 2 + yoffset,
			       child->x + xoffset, child->y +
			       			HEIGHT / 2 + yoffset,
			       plot_style_stroke_history))
			return false;
		if (!browser_window_history__redraw_entry(history, child,
				x0, y0, x1, y1, x, y, clip, ctx))
			return false;
	}

	return true;
}


/**
 * Find the history entry at a position.
 *
 * \param  entry  entry to search from
 * \param  x      coordinate
 * \param  y      coordinate
 * \return  an entry if found, 0 if none
 */

static struct history_entry *browser_window_history__find_position(
		struct history_entry *entry, int x, int y)
{
	struct history_entry *child;
	struct history_entry *found;

	if (!entry)
		return 0;

	if (entry->x <= x && x <= entry->x + WIDTH &&
			entry->y <= y && y <= entry->y + HEIGHT)
		return entry;

	for (child = entry->forward; child; child = child->next) {
		found = browser_window_history__find_position(child, x, y);
		if (found)
			return found;
	}

	return 0;
}

/**
 * Enumerate subentries in history
 * See also history_enumerate()
 *
 * \param	bw		The browser window to enumerate history of
 * \param	entry		entry to start enumeration at
 * \param	cb			callback function
 * \param	ud			context pointer passed to cb
 * \return	true to continue enumeration, false to cancel
 */
static bool browser_window_history__enumerate_entry(
		const struct browser_window *bw,
		const struct history_entry *entry,
		browser_window_history_enumerate_cb cb,
		void *ud)
{
	const struct history_entry *child;

	if (!cb(bw, entry->x, entry->y,
			entry->x + WIDTH, entry->y + HEIGHT,
			entry, ud))
		return false;

	for (child = entry->forward; child; child = child->next) {
		if (!browser_window_history__enumerate_entry(bw, child,
				cb, ud))
			return false;
	}

	return true;
}


/* -------------------------------------------------------------------------- */


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_create(struct browser_window *bw)
{
	struct history *history;

	bw->history = NULL;

	history = calloc(1, sizeof *history);
	if (history == NULL) {
		return NSERROR_NOMEM;
	}

	history->width = RIGHT_MARGIN / 2;
	history->height = BOTTOM_MARGIN / 2;

	bw->history = history;
	return NSERROR_OK;
}


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_clone(const struct browser_window *existing,
		struct browser_window *clone)
{
	struct history *new_history;

	clone->history = NULL;

	if (existing == NULL || existing->history == NULL ||
			existing->history->start == NULL)
		/* Nothing to clone, create new history for clone window */
		return browser_window_history_create(clone);

	/* Make cloned history */
	new_history = malloc(sizeof *new_history);
	if (!new_history)
		return NSERROR_NOMEM;

	clone->history = new_history;
	memcpy(new_history, existing->history, sizeof *new_history);

	new_history->start = browser_window_history__clone_entry(new_history,
			new_history->start);
	if (!new_history->start) {
		LOG("Insufficient memory to clone history");
		browser_window_history_destroy(clone);
		clone->history = NULL;
		return NSERROR_NOMEM;
	}

	return NSERROR_OK;
}


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_add(struct browser_window *bw,
		struct hlcache_handle *content, lwc_string *frag_id)
{
	struct history *history;
	struct history_entry *entry;
	nsurl *nsurl = hlcache_handle_get_url(content);
	char *title;
	struct bitmap *bitmap;
	nserror ret;

	assert(bw);
	assert(bw->history);
	assert(content);

	history = bw->history;

	/* allocate space */
	entry = malloc(sizeof *entry);
	if (entry == NULL) {
		return NSERROR_NOMEM;
	}

	title = strdup(content_get_title(content));
	if (title == NULL) {
		free(entry);
		return NSERROR_NOMEM;
	}

	entry->page.url = nsurl_ref(nsurl);
	entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : 0;

	entry->page.title = title;
	entry->back = history->current;
	entry->next = 0;
	entry->forward = entry->forward_pref = entry->forward_last = 0;
	entry->children = 0;
	entry->bitmap = 0;
	if (history->current) {
		if (history->current->forward_last)
			history->current->forward_last->next = entry;
		else
			history->current->forward = entry;
		history->current->forward_pref = entry;
		history->current->forward_last = entry;
		history->current->children++;
	} else {
		history->start = entry;
	}
	history->current = entry;

	/* if we have a thumbnail, don't update until the page has finished
	 * loading */
	bitmap = urldb_get_thumbnail(nsurl);
	if (bitmap == NULL) {
		LOG("Creating thumbnail for %s", nsurl_access(nsurl));
		bitmap = guit->bitmap->create(WIDTH, HEIGHT,
					      BITMAP_NEW | BITMAP_CLEAR_MEMORY |
					      BITMAP_OPAQUE);
		if (bitmap != NULL) {
			ret = guit->bitmap->render(bitmap, content);
			if (ret == NSERROR_OK) {
				/* Successful thumbnail so register it
				 * with the url.
				 */
				urldb_set_thumbnail(nsurl, bitmap);
			} else {
				/* Thumbnailing failed. Ignore it
				 * silently but clean up bitmap.
				 */
				LOG("Thumbnail renderfailed");
				guit->bitmap->destroy(bitmap);
				bitmap = NULL;
			}
		}
	}
	entry->bitmap = bitmap;

	browser_window_history__layout(history);

	return NSERROR_OK;
}


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_update(struct browser_window *bw,
		struct hlcache_handle *content)
{
	struct history *history;
	char *title;

	assert(bw != NULL);

	history = bw->history;

	if (!history || !history->current || !history->current->bitmap) {
		return NSERROR_INVALID;
	}

	assert(history->current->page.url);
	assert(history->current->page.title);

	title = strdup(content_get_title(content));
	if (title == NULL) {
		return NSERROR_NOMEM;
	}

	free(history->current->page.title);
	history->current->page.title = title;

	guit->bitmap->render(history->current->bitmap, content);

	return NSERROR_OK;
}



/* exported interface documented in desktop/browser_history.h */
void browser_window_history_destroy(struct browser_window *bw)
{
	assert(bw != NULL);

	if (bw->history == NULL)
		return;

	browser_window_history__free_entry(bw->history->start);
	free(bw->history);

	bw->history = NULL;
}
Example #10
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;
}
Example #11
0
/**
 * Clone a content's data members
 *
 * \param c   Content to clone
 * \param nc  Content to populate
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror content__clone(const struct content *c, struct content *nc)
{
	nserror error;

	error = llcache_handle_clone(c->llcache, &(nc->llcache));
	if (error != NSERROR_OK) {
		return error;
	}

	llcache_handle_change_callback(nc->llcache,
				       content_llcache_callback, nc);

	nc->mime_type = lwc_string_ref(c->mime_type);
	nc->handler = c->handler;

	nc->status = c->status;

	nc->width = c->width;
	nc->height = c->height;
	nc->available_width = c->available_width;
	nc->quirks = c->quirks;

	if (c->fallback_charset != NULL) {
		nc->fallback_charset = strdup(c->fallback_charset);
		if (nc->fallback_charset == NULL) {
			return NSERROR_NOMEM;
		}
	}

	if (c->refresh != NULL) {
		nc->refresh = nsurl_ref(c->refresh);
		if (nc->refresh == NULL) {
			return NSERROR_NOMEM;
		}
	}

	nc->time = c->time;
	nc->reformat_time = c->reformat_time;
	nc->size = c->size;

	if (c->title != NULL) {
		nc->title = strdup(c->title);
		if (nc->title == NULL) {
			return NSERROR_NOMEM;
		}
	}

	nc->active = c->active;

	nc->user_list = calloc(1, sizeof(struct content_user));
	if (nc->user_list == NULL) {
		return NSERROR_NOMEM;
	}

	memcpy(&(nc->status_message), &(c->status_message), 120);
	memcpy(&(nc->sub_status), &(c->sub_status), 80);

	nc->locked = c->locked;
	nc->total_size = c->total_size;
	nc->http_code = c->http_code;
	
	return NSERROR_OK;
}
Example #12
0
/**
 * Start fetching data for the given URL.
 *
 * The function returns immediately. The fetch may be queued for later
 * processing.
 *
 * A pointer to an opaque struct curl_fetch_info is returned, which can be
 * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
 * is exhausted (or some other fatal error occurred).
 *
 * The caller must supply a callback function which is called when anything
 * interesting happens. The callback function is first called with msg
 * FETCH_HEADER, with the header in data, then one or more times
 * with FETCH_DATA with some data for the url, and finally with
 * FETCH_FINISHED. Alternatively, FETCH_ERROR indicates an error occurred:
 * data contains an error message. FETCH_REDIRECT may replace the FETCH_HEADER,
 * FETCH_DATA, FETCH_FINISHED sequence if the server sends a replacement URL.
 *
 * Some private data can be passed as the last parameter to fetch_start, and
 * callbacks will contain this.
 */
static void *
fetch_curl_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 curl_fetch_info *fetch;
	struct curl_slist *slist;
	int i;

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

	fetch->fetch_handle = parent_fetch;

	LOG("fetch %p, url '%s'", fetch, nsurl_access(url));

	/* construct a new fetch structure */
	fetch->curl_handle = NULL;
	fetch->had_headers = false;
	fetch->abort = false;
	fetch->stopped = false;
	fetch->only_2xx = only_2xx;
	fetch->downgrade_tls = downgrade_tls;
	fetch->headers = NULL;
	fetch->url = nsurl_ref(url);
	fetch->host = nsurl_get_component(url, NSURL_HOST);
	fetch->location = NULL;
	fetch->content_length = 0;
	fetch->http_code = 0;
	fetch->cookie_string = NULL;
	fetch->realm = NULL;
	fetch->post_urlenc = NULL;
	fetch->post_multipart = NULL;
	if (post_urlenc) {
		fetch->post_urlenc = strdup(post_urlenc);
	} else if (post_multipart) {
		fetch->post_multipart = fetch_curl_post_convert(post_multipart);
	}
	fetch->last_progress_update = 0;

	/* TLS defaults */
	memset(fetch->cert_data, 0, sizeof(fetch->cert_data));
	fetch->cert_depth = -1;

	if ((fetch->host == NULL) ||
	    (post_multipart != NULL && fetch->post_multipart == NULL) ||
	    (post_urlenc != NULL && fetch->post_urlenc == NULL)) {
		goto failed;
	}

#define APPEND(list, value) \
	slist = curl_slist_append(list, value);		\
	if (slist == NULL)				\
		goto failed;				\
	list = slist;

	/* remove curl default headers */
	APPEND(fetch->headers, "Pragma:");

	/* when doing a POST libcurl sends Expect: 100-continue" by default
	 * which fails with lighttpd, so disable it (see bug 1429054) */
	APPEND(fetch->headers, "Expect:");

	if ((nsoption_charp(accept_language) != NULL) &&
	    (nsoption_charp(accept_language)[0] != '\0')) {
		char s[80];
		snprintf(s, sizeof s, "Accept-Language: %s, *;q=0.1",
			 nsoption_charp(accept_language));
		s[sizeof s - 1] = 0;
		APPEND(fetch->headers, s);
	}

	if (nsoption_charp(accept_charset) != NULL &&
	    nsoption_charp(accept_charset)[0] != '\0') {
		char s[80];
		snprintf(s, sizeof s, "Accept-Charset: %s, *;q=0.1",
			 nsoption_charp(accept_charset));
		s[sizeof s - 1] = 0;
		APPEND(fetch->headers, s);
	}

	if (nsoption_bool(do_not_track) == true) {
		APPEND(fetch->headers, "DNT: 1");
	}

	/* And add any headers specified by the caller */
	for (i = 0; headers[i] != NULL; i++) {
		APPEND(fetch->headers, headers[i]);
	}

	return fetch;

#undef APPEND

failed:
	if (fetch->host != NULL)
		lwc_string_unref(fetch->host);

	nsurl_unref(fetch->url);
	free(fetch->post_urlenc);
	if (fetch->post_multipart)
		curl_formfree(fetch->post_multipart);
	curl_slist_free_all(fetch->headers);
	free(fetch);
	return NULL;
}
Example #13
0
void ro_gui_401login_open(nsurl *url, lwc_string *host, const char *realm,
		nserror (*cb)(bool proceed, void *pw), void *cbpw)
{
	struct session_401 *session;
	wimp_w w;
	const char *auth;

	session = calloc(1, sizeof(struct session_401));
	if (!session) {
		warn_user("NoMemory", 0);
		return;
	}

	session->url = nsurl_ref(url);
	if (realm == NULL)
		realm = "Secure Area";
        auth = urldb_get_auth_details(session->url, realm);
	if (auth == NULL) {
		session->uname[0] = '\0';
		session->pwd[0] = '\0';
	} else {
		const char *pwd;
		size_t pwd_len;

		pwd = strchr(auth, ':');
		assert(pwd && pwd < auth + sizeof(session->uname));
		memcpy(session->uname, auth, pwd - auth);
		session->uname[pwd - auth] = '\0';
		++pwd;
		pwd_len = strlen(pwd);
		assert(pwd_len < sizeof(session->pwd));
		memcpy(session->pwd, pwd, pwd_len);
		session->pwd[pwd_len] = '\0';
	}
	session->host = lwc_string_ref(host);
	session->realm = strdup(realm);
	session->cb = cb;
	session->cbpw = cbpw;

	if (!session->realm) {
		nsurl_unref(session->url);
		lwc_string_unref(session->host);
		free(session);
		warn_user("NoMemory", 0);
		return;
	}

	/* fill in download window icons */
	dialog_401_template->icons[ICON_401LOGIN_HOST].data.
			indirected_text.text =
					(char *)lwc_string_data(session->host);
	dialog_401_template->icons[ICON_401LOGIN_HOST].data.
			indirected_text.size =
					lwc_string_length(session->host) + 1;
	dialog_401_template->icons[ICON_401LOGIN_REALM].data.
			indirected_text.text = session->realm;
	dialog_401_template->icons[ICON_401LOGIN_REALM].data.
			indirected_text.size = strlen(session->realm) + 1;
	dialog_401_template->icons[ICON_401LOGIN_USERNAME].data.
			indirected_text.text = session->uname;
	dialog_401_template->icons[ICON_401LOGIN_USERNAME].data.
			indirected_text.size = sizeof(session->uname);
	dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data.
			indirected_text.text = session->pwd;
	dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data.
			indirected_text.size = sizeof(session->pwd);

	/* create and open the window */
	w = wimp_create_window(dialog_401_template);

	ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_USERNAME);
	ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_PASSWORD);
	ro_gui_wimp_event_register_cancel(w, ICON_401LOGIN_CANCEL);
	ro_gui_wimp_event_register_ok(w, ICON_401LOGIN_LOGIN,
			ro_gui_401login_apply);
	ro_gui_wimp_event_register_close_window(w, ro_gui_401login_close);
	ro_gui_wimp_event_set_user_data(w, session);

	ro_gui_dialog_open_persistent(NULL, w, false);
}
Example #14
0
/**
 * Add an entry to the global history (creates the entry).
 *
 * If the treeview has already been created, the entry will be added to the
 * treeview.  Otherwise, the entry will have to be added to the treeview later.
 *
 * When we first create the global history we create it without the treeview, to
 * simplfy sorting the entries.
 *
 * \param url		URL for entry to add to history
 * \param slot		Global history slot to contain history entry
 * \param data		URL data for the entry
 * \param got_treeview	Whether the treeview has been created already
 * \return NSERROR_OK on success, or appropriate error otherwise
 */
static nserror global_history_add_entry_internal(nsurl *url, int slot,
		const struct url_data *data, bool got_treeview)
{
	nserror err;
	struct global_history_entry *e;

	/* Create new local history entry */
	e = malloc(sizeof(struct global_history_entry));
	if (e == NULL) {
		return NSERROR_NOMEM;
	}

	e->user_delete = false;
	e->slot = slot;
	e->url = nsurl_ref(url);
	e->t = data->last_visit;
	e->entry = NULL;
	e->next = NULL;
	e->prev = NULL;

	err = global_history_create_treeview_field_data(e, data);
	if (err != NSERROR_OK) {
		return err;
	}
	
	if (gh_list[slot] == NULL) {
		/* list empty */
		gh_list[slot] = e;

	} else if (gh_list[slot]->t < e->t) {
		/* Insert at list head */
		e->next = gh_list[slot];
		gh_list[slot]->prev = e;
		gh_list[slot] = e;
	} else {
		struct global_history_entry *prev = gh_list[slot];
		struct global_history_entry *curr = prev->next;
		while (curr != NULL) {
			if (curr->t < e->t) {
				break;
			}
			prev = curr;
			curr = curr->next;
		}

		/* insert after prev */
		e->next = curr;
		e->prev = prev;
		prev->next = e;

		if (curr != NULL)
			curr->prev = e;
	}

	if (got_treeview) {
		err = global_history_entry_insert(e, slot);
		if (err != NSERROR_OK) {
			return err;
		}
	}

	return NSERROR_OK;
}