/** * Retrieves a list with unique items from file. * * @filename: file to read items from * @func: function to parse a single line to item * @unique_func: function to decide if two items are equal * @free_func: function to free already converted item if this isn't unique * @max_items: maximum number of items that are returned, use 0 for * unlimited items */ GList *util_file_to_unique_list(const char *filename, Util_Content_Func func, GCompareFunc unique_func, GDestroyNotify free_func, unsigned int max_items) { GList *gl = NULL; /* yes, the whole file is read and wen possible don not need all the * lines, but this is easier to implement compared to reading the file * line wise from end to beginning */ char *line, **lines; void *value; int len, num_items = 0; /* return empty list if max items is 0 */ if (!max_items) { return gl; } lines = util_get_lines(filename); len = g_strv_length(lines); if (!len) { return gl; } /* begin with the last line of the file to make unique check easier - * every already existing item in the list is the latest, so we don't need * to remove items from the list which takes some time */ for (int i = len - 1; i >= 0; i--) { line = lines[i]; g_strstrip(line); if (!*line) { continue; } if ((value = func(line))) { /* if the value is already in list, free it and don't put it onto * the list */ if (g_list_find_custom(gl, value, unique_func)) { free_func(value); } else { gl = g_list_prepend(gl, value); /* skip the loop if we precessed max_items unique items */ if (++num_items >= max_items) { break; } } } } g_strfreev(lines); return gl; }
/** * Reads the entries save in given file and store them in the whitelist. */ static void load_entries(HSTSProvider *provider, const char *file) { char **lines, **parts, *host, *line; int i, len, partlen; gboolean include_sub_domains; SoupDate *date; HSTSEntry *entry; lines = util_get_lines(file); if (!(len = g_strv_length(lines))) { return; } for (i = len - 1; i >= 0; i--) { line = lines[i]; /* skip empty or commented lines */ if (!*line || *line == '#') { continue; } parts = g_strsplit(line, "\t", 3); partlen = g_strv_length(parts); if (partlen == 3) { host = parts[0]; if (g_hostname_is_ip_address(host)) { continue; } date = soup_date_new_from_string(parts[1]); if (!date) { continue; } include_sub_domains = (*parts[2] == 'y') ? true : false; /* built the new entry to add */ entry = g_slice_new(HSTSEntry); entry->expires_at = soup_date_new_from_string(parts[1]); entry->include_sub_domains = include_sub_domains; add_host_entry(provider, host, entry); } else { g_warning("could not parse hsts line '%s'", line); } g_strfreev(parts); } g_strfreev(lines); }