hfc

Hosts file client
git clone git://git.marlonivo.com/hfc
Log | Files | Refs | LICENSE

get.c (4327B)


      1 /* get.c - download and save hosts entries from URL sources
      2 *
      3 * headers and macros */
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <curl/curl.h>
      8 #include <ctype.h>
      9 
     10 #include "get.h"
     11 #include "hfc.h"
     12 
     13 #define HOSTS_FILE_PATH "/etc/hosts"
     14 
     15 struct MemoryStruct {
     16 	char *memory;
     17 	size_t size;
     18 };
     19 
     20 static size_t
     21 WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
     22 {
     23 	size_t realsize;
     24 	char *ptr;
     25 	struct MemoryStruct *mem;
     26 
     27 	realsize = size * nmemb;
     28 	mem = (struct MemoryStruct *)userp;
     29 
     30 	ptr = realloc(mem->memory, mem->size + realsize + 1);
     31 	if (!ptr)
     32 		return 0;
     33 
     34 	mem->memory = ptr;
     35 	memcpy(&(mem->memory[mem->size]), contents, realsize);
     36 	mem->size += realsize;
     37 	mem->memory[mem->size] = '\0';
     38 
     39 	return realsize;
     40 }
     41 
     42 char *
     43 download_url(const char *url, char *error_msg, size_t err_size)
     44 {
     45 	CURL *curl_handle;
     46 	CURLcode res;
     47 	struct MemoryStruct chunk;
     48 
     49 	chunk.memory = malloc(1);
     50 	chunk.size = 0;
     51 
     52 	curl_handle = curl_easy_init();
     53 	if (!curl_handle) {
     54 		snprintf(error_msg, err_size, "Could not initialize CURL");
     55 		free(chunk.memory);
     56 		return NULL;
     57 	}
     58 
     59 	char user_agent[64];
     60 	snprintf(user_agent, sizeof(user_agent), "hfc/%s", HFC_VERSION);
     61 
     62 	curl_easy_setopt(curl_handle, CURLOPT_URL, url);
     63 	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
     64 	curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
     65 	curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent);
     66 	curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, error_msg);
     67 	curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0L);
     68 
     69 	res = curl_easy_perform(curl_handle);
     70 	if (res != CURLE_OK) {
     71 		free(chunk.memory);
     72 		chunk.memory = NULL;
     73 	} else {
     74 		error_msg[0] = '\0';
     75 	}
     76 
     77 	curl_easy_cleanup(curl_handle);
     78 	return chunk.memory;
     79 }
     80 
     81 long
     82 get_remote_content_length(const char *url)
     83 {
     84 	CURL *curl;
     85 	CURLcode res;
     86 	curl_off_t clength = -1;
     87 
     88 	curl = curl_easy_init();
     89 	if (!curl)
     90 		return -1;
     91 
     92 	char user_agent[64];
     93 	snprintf(user_agent, sizeof(user_agent), "hfc/%s", HFC_VERSION);
     94 	curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent);
     95 	curl_easy_setopt(curl, CURLOPT_URL, url);
     96 	curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
     97 	curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
     98 	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
     99 	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
    100 	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
    101 
    102 	res = curl_easy_perform(curl);
    103 	if (res == CURLE_OK) {
    104 		if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &clength) != CURLE_OK)
    105 			clength = -1;
    106 	}
    107 
    108 	curl_easy_cleanup(curl);
    109 	return (clength >= 0) ? (long)clength : -1;
    110 }
    111 
    112 int
    113 contains_valid_hosts_entry(const char *content)
    114 {
    115 	const char *line, *next_line;
    116 	size_t len;
    117 	char *cr;
    118 	char buffer[512];
    119 
    120 	if (!content)
    121 		return 0;
    122 
    123 	line = content;
    124 	while (*line) {
    125 		next_line = strchr(line, '\n');
    126 		len = next_line ? (size_t)(next_line - line) : strlen(line);
    127 
    128 		if (len >= sizeof(buffer))
    129 			len = sizeof(buffer) - 1;
    130 
    131 		if (len > 0) {
    132 			memcpy(buffer, line, len);
    133 			buffer[len] = '\0';
    134 
    135 			cr = strchr(buffer, '\r');
    136 			if (cr)
    137 				*cr = '\0';
    138 
    139 			while (*buffer == ' ' || *buffer == '\t')
    140 				memmove(buffer, buffer + 1, strlen(buffer));
    141 
    142 			if (strncmp(buffer, "0.0.0.0 ", 8) == 0 ||
    143 				strncmp(buffer, "127.0.0.1 ", 10) == 0)
    144 				return 1;
    145 		}
    146 
    147 		if (!next_line)
    148 			break;
    149 		line = next_line + 1;
    150 	}
    151 
    152 	return 0;
    153 }
    154 
    155 int
    156 save_to_hosts_file(const char *content, const char *url, int number)
    157 {
    158 	FILE *fp;
    159 	const char *line, *next_line;
    160 	size_t len;
    161 	char *cr;
    162 	char buffer[512], ip[16], domain[256];
    163 
    164 	if (!content)
    165 		return 0;
    166 
    167 	fp = fopen(HOSTS_FILE_PATH, "a");
    168 	if (!fp)
    169 		return 0;
    170 
    171 	fprintf(fp, "# %d. %s\n", number, url);
    172 
    173 	line = content;
    174 	while (*line) {
    175 		next_line = strchr(line, '\n');
    176 		len = next_line ? (size_t)(next_line - line) : strlen(line);
    177 
    178 		if (len >= sizeof(buffer))
    179 			len = sizeof(buffer) - 1;
    180 
    181 		if (len > 0) {
    182 			memcpy(buffer, line, len);
    183 			buffer[len] = '\0';
    184 
    185 			cr = strchr(buffer, '\r');
    186 			if (cr)
    187 				*cr = '\0';
    188 
    189 			while (*buffer == ' ' || *buffer == '\t')
    190 				memmove(buffer, buffer + 1, strlen(buffer));
    191 
    192 			if (sscanf(buffer, "%15s %255s", ip, domain) == 2) {
    193 				if (!strcmp(ip, "127.0.0.1") || !strcmp(ip, "0.0.0.0"))
    194 					fprintf(fp, "0.0.0.0 %s\n", domain);
    195 			}
    196 		}
    197 
    198 		if (!next_line)
    199 			break;
    200 		line = next_line + 1;
    201 	}
    202 
    203 	fclose(fp);
    204 	return 1;
    205 }