static struct magnet_source * magnet_parse_location(const char *uri, const char **error_str) { struct magnet_source *ms; const char *p, *host, *host_end; host_addr_t addr; uint16 port; clear_error_str(&error_str); g_return_val_if_fail(uri, NULL); p = uri; p = magnet_parse_host_port(uri, &addr, &port, &host, &host_end, error_str); if (NULL == p) return NULL; ms = magnet_parse_path(p, error_str); if (NULL == ms) return NULL; if (host) { char *h = h_strndup(host, host_end - host); ms->hostname = atom_str_get(h); HFREE_NULL(h); } ms->addr = addr; ms->port = port; return ms; }
/** * Creates a copy with the given pathname with the basename cut off. A slash * is always considered a separator but G_DIR_SEPARATOR is considered as * well. Thus "/whatever/blah\\yadda" returns "/whatever/blah" if G_DIR_SEPARATOR * is a backslash, otherwise "/whatever" is returned. * * @return A newly allocated string holding the given pathname with the * basename cut off. If the string contained no directory separator, * NULL is returned. The string must be freed via hfree(). */ char * filepath_directory(const char *pathname) { const char *sep; char *dir; sep = filepath_directory_end(pathname, '/'); if (G_DIR_SEPARATOR != '/') { const char *alt; alt = filepath_directory_end(pathname, G_DIR_SEPARATOR); if (sep && alt) { sep = (sep - pathname > alt - pathname) ? sep : alt; } else if (alt) { sep = alt; } } if (sep == pathname) { dir = h_strdup(G_DIR_SEPARATOR_S); } else if (sep) { dir = h_strndup(pathname, sep - pathname); } else { dir = NULL; } return dir; }
/** * Extract interest flags from the payload of a /Q2/I tree node. * * @return the consolidated flags G2_Q2_F_* requested by the payload. */ static uint32 g2_node_extract_interest(const g2_tree_t *t) { const char *p, *q, *end; size_t paylen; uint32 flags = 0; p = q = g2_tree_node_payload(t, &paylen); if (NULL == p) return 0; end = p + paylen; while (q != end) { if ('\0' == *q++) { flags |= TOKENIZE(p, g2_q2_i); p = q; } } if (p != q) { char *r = h_strndup(p, q - p); /* String not NUL-terminated */ flags |= TOKENIZE(r, g2_q2_i); hfree(r); } return flags; }
/** * Extract variable name from string `s', then fetch value from environment. * * @return variable's value, or "" if not found and set `end' to the address * of the character right after the variable name. */ static const char * get_variable(const char *s, const char **end) { const char *value, *p = s; bool end_brace = FALSE; /* * Grab variable's name. */ if (*p == '{') { p++; s++; end_brace = TRUE; } while (is_ascii_alnum(*p) || *p == '_') { p++; } if (end_brace && *p == '}') *end = &p[1]; else *end = p; /* * Get value from environment. */ { char *name; name = h_strndup(s, p - s); value = getenv(name); if (value == NULL) value = ""; if (common_dbg > 4) g_debug("variable \"%s\" is \"%s\"", name, value); HFREE_NULL(name); } return value; }
static void html_output_print(struct html_output *output, const struct array *text) { struct html_context *ctx; if (text->size <= 0) return; ctx = html_output_get_udata(output); if (ctx->title) { str_cat_len(ctx->title, text->data, text->size); return; } #if GTK_CHECK_VERSION(2,0,0) { GtkTextBuffer *buffer; GtkTextIter iter; buffer = gtk_text_view_get_buffer(ctx->html_view->widget); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert(buffer, &iter, text->data, text->size); } #else { struct array str; gchar *to_free; if (locale_is_utf8()) { str = array_init(text->data, text->size); to_free = NULL; } else { to_free = h_strndup(text->data, text->size); str = array_from_string(lazy_utf8_to_ui_string(to_free)); } gtk_text_insert(ctx->html_view->widget, NULL, NULL, NULL, str.data, str.size); HFREE_NULL(to_free); } #endif }
/** * Intuit the media type they are searching based on the first XML tag * we find in the meta data string, using simplistic lexical parsing which * will encompass 99% of the cases. */ static uint32 g2_node_intuit_media_type(const char *md) { const char *p = md; const char *start; int c; uint32 flags; while ('<' != (c = *p++) && c != 0) /* empty */; if (0 == c) return 0; /* Did not find any tag opening */ start = p = skip_ascii_spaces(p); while (0 != (c = *p)) { if (is_ascii_space(c) || '/' == c || '>' == c) { char *name; /* Found end of word, we got the tag name */ name = h_strndup(start, p - start); flags = TOKENIZE(name, g2_q2_md); if (0 == flags) { g_warning("%s(): unknown tag \"%s\", XML string was \"%s\"", G_STRFUNC, name, md); } hfree(name); return flags; } p++; } return 0; }
/** * Handle reception of a /Q2 */ static void g2_node_handle_q2(gnutella_node_t *n, const g2_tree_t *t) { const guid_t *muid; size_t paylen; const g2_tree_t *c; char *dn = NULL; char *md = NULL; uint32 iflags = 0; search_request_info_t sri; bool has_interest = FALSE; node_inc_rx_query(n); /* * As a G2 leaf, we cannot handle queries coming from UDP because we * are not supposed to get any! */ if (NODE_IS_UDP(n)) { g2_node_drop(G_STRFUNC, n, t, "coming from UDP"); return; } /* * The MUID of the query is the payload of the root node. */ muid = g2_tree_node_payload(t, &paylen); if (paylen != GUID_RAW_SIZE) { g2_node_drop(G_STRFUNC, n, t, "missing MUID"); return; } /* * Make sure we have never seen this query already. * * To be able to leverage on Gnutella's routing table to detect duplicates * over a certain lifespan, we are going to fake a minimal Gnutella header * with a message type of GTA_MSG_G2_SEARCH, which is never actually used * on the network. * * The TTL and hops are set to 1 and 0 initially, so that the message seems * to come from a neighbouring host and cannot be forwarded. * * When that is done, we will be able to call route_message() and have * all the necessary bookkeeping done for us. */ { struct route_dest dest; gnutella_header_set_muid(&n->header, muid); gnutella_header_set_function(&n->header, GTA_MSG_G2_SEARCH); gnutella_header_set_ttl(&n->header, 1); gnutella_header_set_hops(&n->header, 0); if (!route_message(&n, &dest)) return; /* Already accounted as duplicated, and logged */ } /* * Setup request information so that we can call search_request() * to process our G2 query. */ ZERO(&sri); sri.magic = SEARCH_REQUEST_INFO_MAGIC; /* * Handle the children of /Q2. */ G2_TREE_CHILD_FOREACH(t, c) { enum g2_q2_child ct = TOKENIZE(g2_tree_name(c), g2_q2_children); const char *payload; switch (ct) { case G2_Q2_DN: payload = g2_tree_node_payload(c, &paylen); if (payload != NULL && NULL == dn) { uint off = 0; /* Not NUL-terminated, need to h_strndup() it */ dn = h_strndup(payload, paylen); if (!query_utf8_decode(dn, &off)) { gnet_stats_count_dropped(n, MSG_DROP_MALFORMED_UTF_8); goto done; /* Drop the query */ } sri.extended_query = dn + off; sri.search_len = paylen - off; /* In bytes */ } break; case G2_Q2_I: if (!has_interest) iflags = g2_node_extract_interest(c); has_interest = TRUE; break; case G2_Q2_MD: payload = g2_tree_node_payload(c, &paylen); if (payload != NULL && NULL == md) { /* Not NUL-terminated, need to h_strndup() it */ md = h_strndup(payload, paylen); } break; case G2_Q2_NAT: sri.flags |= QUERY_F_FIREWALLED; break; case G2_Q2_SZR: /* Size limits */ if (g2_node_extract_size_request(c, &sri.minsize, &sri.maxsize)) sri.size_restrictions = TRUE; break; case G2_Q2_UDP: if (!sri.oob) g2_node_extract_udp(c, &sri, n); break; case G2_Q2_URN: g2_node_extract_urn(c, &sri); break; } } /* * When there is no /Q2/I, return a default set of information. */ if (!has_interest) iflags = G2_Q2_F_DFLT; /* * If there are meta-data, try to intuit which media types there are * looking for. * * The payload is XML looking like "<audio/>" or "<video/>" but there * can be attributes and we don't want to do a full XML parsing there. * Hence we'll base our analysis on simple lexical parsing, which is * why we call a routine to "intuit", not to "extract". * * Also, this is poorer than Gnutella's GGEP "M" because apparently there * can be only one single type, since the XML payload must obey some * kind of schema and there is an audio schema, a video schema, etc... * XML was just a wrong design choice there. */ if (md != NULL) sri.media_types = g2_node_intuit_media_type(md); /* * Validate the return address if OOB hit delivery is configured. */ if (sri.oob && !search_oob_is_allowed(n, &sri)) goto done; /* * Update statistics, as done in search_request_preprocess() for Gnutella. */ if (sri.exv_sha1cnt) { gnet_stats_inc_general(GNR_QUERY_G2_SHA1); if (NULL == dn) { int i; for (i = 0; i < sri.exv_sha1cnt; i++) { search_request_listener_emit(QUERY_SHA1, sha1_base32(&sri.exv_sha1[i].sha1), n->addr, n->port); } } } if (dn != NULL && !is_ascii_string(dn)) gnet_stats_inc_general(GNR_QUERY_G2_UTF8); if (dn != NULL) search_request_listener_emit(QUERY_STRING, dn, n->addr, n->port); if (!search_is_valid(n, 0, &sri)) goto done; /* * Perform the query. */ sri.g2_query = TRUE; sri.partials = booleanize(iflags & G2_Q2_F_PFS); sri.g2_wants_url = booleanize(iflags & G2_Q2_F_URL); sri.g2_wants_alt = booleanize(iflags & G2_Q2_F_A); sri.g2_wants_dn = booleanize(iflags & G2_Q2_F_DN); search_request(n, &sri, NULL); done: HFREE_NULL(dn); HFREE_NULL(md); }
struct magnet_resource * magnet_parse(const char *url, const char **error_str) { static const struct magnet_resource zero_resource; struct magnet_resource res; const char *p, *next; res = zero_resource; clear_error_str(&error_str); p = is_strcaseprefix(url, "magnet:"); if (!p) { *error_str = "Not a MAGNET URI"; return NULL; } if ('?' != p[0]) { *error_str = "Invalid MAGNET URI"; return NULL; } p++; for (/* NOTHING */; p && '\0' != p[0]; p = next) { enum magnet_key key; const char *endptr; char name[16]; /* Large enough to hold longest key we know */ name[0] = '\0'; endptr = strchr(p, '='); if (endptr && p != endptr) { size_t name_len; name_len = endptr - p; g_assert(size_is_positive(name_len)); if (name_len < sizeof name) { /* Ignore overlong key */ strncat(name, p, name_len); } p = &endptr[1]; /* Point behind the '=' */ } endptr = strchr(p, '&'); if (!endptr) { endptr = strchr(p, '\0'); } key = magnet_key_get(name); if (MAGNET_KEY_NONE == key) { g_message("skipping unknown key \"%s\" in MAGNET URI", name); } else { char *value; size_t value_len; value_len = endptr - p; value = h_strndup(p, value_len); plus_to_space(value); if (url_unescape(value, TRUE)) { magnet_handle_key(&res, name, value); } else { g_message("badly encoded value in MAGNET URI: \"%s\"", value); } HFREE_NULL(value); } while ('&' == endptr[0]) { endptr++; } next = endptr; } res.sources = g_slist_reverse(res.sources); res.searches = g_slist_reverse(res.searches); return wcopy(&res, sizeof res); }
/** * Loads the whitelist into memory. */ static void G_COLD whitelist_retrieve(void) { char line[1024]; FILE *f; filestat_t st; unsigned linenum = 0; file_path_t fp[1]; whitelist_generation++; file_path_set(fp, settings_config_dir(), whitelist_file); f = file_config_open_read_norename("Host Whitelist", fp, N_ITEMS(fp)); if (!f) return; if (fstat(fileno(f), &st)) { g_warning("%s(): fstat() failed: %m", G_STRFUNC); fclose(f); return; } while (fgets(line, sizeof line, f)) { pslist_t *sl_addr, *sl; const char *endptr, *start; host_addr_t addr; uint16 port; uint8 bits; bool item_ok; bool use_tls; char *hname; linenum++; if (!file_line_chomp_tail(line, sizeof line, NULL)) { g_warning("%s(): line %u too long, aborting", G_STRFUNC, linenum); break; } if (file_line_is_skipable(line)) continue; sl_addr = NULL; addr = zero_host_addr; endptr = NULL; hname = NULL; endptr = is_strprefix(line, "tls:"); if (endptr) { use_tls = TRUE; start = endptr; } else { use_tls = FALSE; start = line; } port = 0; if (string_to_host_addr_port(start, &endptr, &addr, &port)) { sl_addr = name_to_host_addr(host_addr_to_string(addr), settings_dns_net()); } else if (string_to_host_or_addr(start, &endptr, &addr)) { uchar c = *endptr; switch (c) { case '\0': case ':': case '/': break; default: if (!is_ascii_space(c)) endptr = NULL; } if (!endptr) { g_warning("%s(): line %d: " "expected a hostname or IP address \"%s\"", G_STRFUNC, linenum, line); continue; } /* Terminate the string for name_to_host_addr() */ hname = h_strndup(start, endptr - start); } else { g_warning("%s(): line %d: expected hostname or IP address \"%s\"", G_STRFUNC, linenum, line); continue; } g_assert(sl_addr != NULL || hname != NULL); g_assert(NULL != endptr); bits = 0; item_ok = TRUE; /* * When an explicit address is given (no hostname) and with no * port, one can suffix the address with bits to indicate a CIDR * range of whitelisted addresses. */ if (0 == port) { /* Ignore trailing items separated by a space */ while ('\0' != *endptr && !is_ascii_space(*endptr)) { uchar c = *endptr++; if (':' == c) { int error; uint32 v; if (0 != port) { g_warning("%s(): line %d: multiple colons after host", G_STRFUNC, linenum); item_ok = FALSE; break; } v = parse_uint32(endptr, &endptr, 10, &error); port = (error || v > 0xffff) ? 0 : v; if (0 == port) { g_warning("%s(): line %d: " "invalid port value after host", G_STRFUNC, linenum); item_ok = FALSE; break; } } else if ('/' == c) { const char *ep; uint32 mask; if (0 != bits) { g_warning("%s(): line %d: " "multiple slashes after host", G_STRFUNC, linenum); item_ok = FALSE; break; } if (string_to_ip_strict(endptr, &mask, &ep)) { if (!host_addr_is_ipv4(addr)) { g_warning("%s(): line %d: " "IPv4 netmask after non-IPv4 address", G_STRFUNC, linenum); item_ok = FALSE; break; } endptr = ep; if (0 == (bits = netmask_to_cidr(mask))) { g_warning("%s(): line %d: " "IPv4 netmask after non-IPv4 address", G_STRFUNC, linenum); item_ok = FALSE; break; } } else { int error; uint32 v; v = parse_uint32(endptr, &endptr, 10, &error); if ( error || 0 == v || (v > 32 && host_addr_is_ipv4(addr)) || (v > 128 && host_addr_is_ipv6(addr)) ) { g_warning("%s(): line %d: " "invalid numeric netmask after host", G_STRFUNC, linenum); item_ok = FALSE; break; } bits = v; } } else { g_warning("%s(): line %d: " "unexpected character after host", G_STRFUNC, linenum); item_ok = FALSE; break; } } } if (item_ok) { struct whitelist *item; if (hname) { item = whitelist_hostname_create(use_tls, hname, port); whitelist_dns_resolve(item, FALSE); } else { PSLIST_FOREACH(sl_addr, sl) { host_addr_t *aptr = sl->data; g_assert(aptr != NULL); item = whitelist_addr_create(use_tls, *aptr, port, bits); whitelist_add(item); } } } else {
static void html_output_tag(struct html_output *output, const struct array *tag) #if GTK_CHECK_VERSION(2,0,0) { static struct { gboolean initialized; short_string_t centre_line, nbsp, bullet, soft_hyphen, em_dash; short_string_t list_item_prefix; } special; struct html_context *ctx; const gchar *style, *text, *attr; enum html_tag id; gboolean closing; GtkTextBuffer *buffer; if (!special.initialized) { special.initialized = TRUE; special.bullet = utf8_char(0x2022); special.centre_line = utf8_char(0xFE4E); special.soft_hyphen = utf8_char(0x00AD); special.nbsp = utf8_char(0x00A0); special.em_dash = utf8_char(0x2014); concat_strings(special.list_item_prefix.str, sizeof special.list_item_prefix.str, " ", special.bullet.str, " ", (void *) 0); } style = NULL; text = NULL; attr = NULL; closing = html_tag_is_closing(tag); ctx = html_output_get_udata(output); id = html_parse_tag(tag); buffer = gtk_text_view_get_buffer(ctx->html_view->widget); switch (id) { case HTML_TAG_BODY: style = STYLE_TAG_WORD_WRAP; break; case HTML_TAG_A: if (closing) { if (ctx->start[id] && ctx->href) { GtkTextIter start, end; GtkTextTag *anchor; anchor = gtk_text_buffer_create_tag(buffer, NULL, (void *) 0); g_object_set_data(G_OBJECT(anchor), "href", deconstify_gchar(ctx->href)); gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag(buffer, anchor, &start, &end); style = get_style_for_href(ctx->href); ctx->href = NULL; } } else { struct array value; value = html_get_attribute(tag, HTML_ATTR_HREF); if (value.data && value.size > 0) { GtkTextIter iter; ctx->href = g_strndup(value.data, value.size); ctx->html_view->to_free = g_slist_prepend( ctx->html_view->to_free, deconstify_gchar(ctx->href)); gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); g_object_set_data(G_OBJECT(ctx->start[id]), "href", deconstify_gchar(ctx->href)); } value = html_get_attribute(tag, HTML_ATTR_NAME); if (value.data && value.size > 0) { GtkTextTagTable *table; gchar name[256]; size_t n; n = sizeof name - 2; n = MIN(value.size, n); name[0] = '#'; memcpy(&name[1], value.data, n); name[n + 1] = '\0'; table = gtk_text_buffer_get_tag_table(buffer); if (NULL == gtk_text_tag_table_lookup(table, name)) { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_create_mark(buffer, name, &iter, TRUE); } } } break; case HTML_TAG_B: case HTML_TAG_STRONG: case HTML_TAG_THEAD: style = STYLE_TAG_BOLD; break; case HTML_TAG_TH: if (closing) text = "\t"; break; case HTML_TAG_EM: style = STYLE_TAG_UNDERLINE; break; case HTML_TAG_I: case HTML_TAG_Q: style = STYLE_TAG_ITALIC; break; case HTML_TAG_IMG: if (!closing) { struct array value; static gchar alt[1024]; value = html_get_attribute(tag, HTML_ATTR_ALT); if (value.data) { gm_snprintf(alt, sizeof alt, "\n[image alt=\"%.*s\"]\n", (int)value.size, value.data); text = alt; } value = html_get_attribute(tag, HTML_ATTR_SRC); if (value.data) { GdkPixbuf *pixbuf; gchar *filename; GtkTextIter iter; filename = h_strndup(value.data, value.size); pixbuf = gdk_pixbuf_new_from_file(filename, NULL); if (pixbuf) { gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf); } else { static gchar msg[1024]; gm_snprintf(msg, sizeof msg, "\n[Image not found (\"%s\")]\n", filename); text = msg; } HFREE_NULL(filename); } if (!text) { text = "\n[image]\n"; } } attr = STYLE_TAG_BOLD; break; case HTML_TAG_TD: if (closing) text = "\t"; break; case HTML_TAG_P: case HTML_TAG_DIV: text = closing ? "\n\n" : special.soft_hyphen.str; break; case HTML_TAG_DL: case HTML_TAG_TABLE: case HTML_TAG_TR: case HTML_TAG_UL: case HTML_TAG_OL: case HTML_TAG_BR: text = "\n"; break; case HTML_TAG_DT: case HTML_TAG_LI: if (closing) { GtkTextIter start, end; GtkTextTag *margin; PangoLayout *pl; gint width; pl = pango_layout_new(gtk_widget_get_pango_context( GTK_WIDGET(ctx->html_view->widget))); pango_layout_set_text(pl, special.list_item_prefix.str, -1); pango_layout_get_pixel_size(pl, &width, NULL); g_object_unref(G_OBJECT(pl)); margin = gtk_text_buffer_create_tag(buffer, NULL, "left-margin", width * 2, "left-margin-set", TRUE, (void *) 0); gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag(buffer, margin, &start, &end); } else { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert(buffer, &iter, "\n", (-1)); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, special.list_item_prefix.str, (-1), STYLE_TAG_BOLD, (void *) 0); gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); } break; case HTML_TAG_CODE: case HTML_TAG_KBD: case HTML_TAG_PRE: case HTML_TAG_TT: style = STYLE_TAG_MONOSPACE; break; case HTML_TAG_H1: style = STYLE_TAG_HEADING_1; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_H2: style = STYLE_TAG_HEADING_2; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_H3: style = STYLE_TAG_HEADING_3; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_H4: case HTML_TAG_H5: case HTML_TAG_H6: style = STYLE_TAG_HEADING_4; text = closing ? "\n\n" : "\n"; break; case HTML_TAG_TITLE: if (closing) { if (ctx->title) { GtkWidget *window; window = gtk_widget_get_toplevel( GTK_WIDGET(ctx->html_view->widget)); gtk_window_set_title(GTK_WINDOW(window), str_2c(ctx->title)); str_destroy_null(&ctx->title); } } else { ctx->title = str_new(0); } break; case HTML_TAG_HR: { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, "\n \n", (-1), STYLE_TAG_CENTER, STYLE_TAG_UNDERLINE, (void *) 0); } text = "\n"; break; case HTML_TAG_COMMENT: #if 0 { GtkTextIter iter; /* Comments can be made visible this way */ ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, tag->data, tag->size, STYLE_TAG_ITALIC, (void *) 0); } closing = TRUE; text = "\n"; #endif break; case HTML_TAG_HTML: if (closing) { if (ctx->lang && ctx->start[id]) { GtkTextIter start, end; GtkTextTag *lang; lang = gtk_text_buffer_create_tag(buffer, NULL, "language", ctx->lang, "language-set", TRUE, (void *) 0); gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag(buffer, lang, &start, &end); ctx->lang = NULL; } } else { struct array value; value = html_get_attribute(tag, HTML_ATTR_LANG); if (value.data && value.size > 0) { GtkTextIter iter; ctx->lang = g_strndup(value.data, value.size); ctx->html_view->to_free = g_slist_prepend( ctx->html_view->to_free, deconstify_gchar(ctx->lang)); gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); } } case HTML_TAG_HEAD: case HTML_TAG_META: case HTML_TAG_SPAN: case HTML_TAG_COL: case HTML_TAG_DD: case HTML_TAG_TBODY: case HTML_TAG_DOCTYPE: case HTML_TAG_UNKNOWN: break; case NUM_HTML_TAG: g_assert_not_reached(); } if (style) { if (closing) { if (ctx->start[id]) { GtkTextIter start, end; gtk_text_buffer_get_iter_at_mark(buffer, &start, ctx->start[id]); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_apply_tag_by_name(buffer, style, &start, &end); ctx->start[id] = NULL; } } else { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); ctx->start[id] = gtk_text_buffer_create_mark(buffer, NULL, &iter, TRUE); } } if (text) { GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, text, (-1), attr, (void *) 0); } }
/** * Called from gwc_parse_dispatch_lines() for each complete line of output. * * @return FALSE to stop processing of any remaining data. */ static bool gwc_host_line(struct gwc_parse_context *ctx, const char *buf, size_t len) { int c; if (GNET_PROPERTY(bootstrap_debug) > 3) g_message("BOOT GWC host line (%lu bytes): %s", (ulong) len, buf); if (is_strprefix(buf, "ERROR")) { g_warning("GWC cache \"%s\" returned %s", http_async_url(ctx->handle), buf); http_async_cancel(ctx->handle); return FALSE; } if (len <= 2) return TRUE; /* Skip this line silently */ /* * A line starting with "H|" is a host, with "U|" a GWC URL. * Letters are case-insensitive. */ if (buf[1] != '|') goto malformed; c = ascii_toupper(buf[0]); if ('H' == c) { host_addr_t addr; uint16 port; if (string_to_host_addr_port(&buf[2], NULL, &addr, &port)) { ctx->processed++; hcache_add_caught(HOST_G2HUB, addr, port, "GWC"); if (GNET_PROPERTY(bootstrap_debug) > 1) { g_message("BOOT (G2) collected %s from GWC %s", host_addr_port_to_string(addr, port), http_async_url(ctx->handle)); } } return TRUE; } else if ('U' == c) { char *end = strchr(&buf[2], '|'); char *url; if (NULL == end) goto malformed; ctx->processed++; url = h_strndup(&buf[2], ptr_diff(end, &buf[2])); gwc_add(url); hfree(url); return TRUE; } else if ('I' == c) { return TRUE; /* Ignore information line */ } /* * If we come here, we did not recognize the line properly. */ if (GNET_PROPERTY(bootstrap_debug) > 2) { g_warning("GWC ignoring unknown line \"%s\" from %s", buf, http_async_url(ctx->handle)); } return TRUE; malformed: if (GNET_PROPERTY(bootstrap_debug)) { g_warning("GWC ignoring malformed line \"%s\" from %s", buf, http_async_url(ctx->handle)); } return TRUE; }