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); }
/** 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; }
END_TEST /** * check ref asserts on NULL parameter */ START_TEST(nsurl_api_assert_ref_test) { nsurl_ref(NULL); }
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; }
/* 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); }
/** 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; }
/** 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; }
/** * 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; }
/** * 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; }
/* 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; }
/** * 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; }
/** * 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; }
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); }
/** * 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; }