1 /* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
2 /* gnome-netinfo - A GUI Interface for network utilities
3  * Copyright (C) 2003 by William Jon McCann
4  * Copyright (C) 2003 by German Poo-Caaman~o
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <gtk/gtk.h>
26 #include <glib/gi18n.h>
27 #include <glib/gprintf.h>
28 #include <sys/types.h>
29 
30 #include "lookup.h"
31 #include "utils.h"
32 #include <regex.h>
33 
34 static gint strip_line (gchar * line, lookup_data * data);
35 static GtkTreeModel * lookup_create_model (GtkTreeView *widget);
36 
37 void
lookup_stop(Netinfo * netinfo)38 lookup_stop (Netinfo * netinfo)
39 {
40 	g_return_if_fail (netinfo != NULL);
41 
42 	netinfo_stop_process_command (netinfo);
43 }
44 
45 static int
pattern_match(const char * string,const char * pattern)46 pattern_match (const char *string, const char *pattern)
47 {
48 	int status;
49 	regex_t re;
50 	if (regcomp (&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
51                 return FALSE;      /* report error */
52 	}
53 	status = regexec (&re, string, (size_t) 0, NULL, 0);
54 	regfree (&re);
55 
56 	if (status != 0) {
57 		return FALSE;      /* report error */
58 	}
59 	return TRUE;
60 }
61 
62 
63 void
lookup_do(Netinfo * netinfo)64 lookup_do (Netinfo * netinfo)
65 {
66 	const gchar *host = NULL;
67 	gchar *command = NULL;
68 	gchar *program = NULL;
69 	GtkTreeModel *model;
70 	GtkWidget *parent;
71 	gboolean use_reverse_lookup;
72 	const gchar *address_regular_expression = "^[ ]*[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}[ ]*$";
73 	gint active_index;
74 	const gchar *query_types[12] = {"", "A", "CNAME", "HINFO", "MX", "MINFO", "NS", "PTR", "SOA", "TXT", "WKS", "ANY"};
75 	gchar **command_line;
76 	gchar **command_options;
77 	gint i, j, num_terms;
78 
79 	g_return_if_fail (netinfo != NULL);
80 
81 	host = netinfo_get_host (netinfo);
82 
83 	if (netinfo->stbar_text)
84 		g_free (netinfo->stbar_text);
85 	netinfo->stbar_text = g_strdup_printf (_("Looking up %s"), host);
86 
87 	if (netinfo_validate_domain (netinfo) == FALSE) {
88 		netinfo_stop_process_command (netinfo);
89 		return;
90 	}
91 
92 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (netinfo->output));
93 	if (GTK_IS_LIST_STORE (model)) {
94 		gtk_list_store_clear (GTK_LIST_STORE (model));
95 	}
96 
97 	active_index = gtk_combo_box_get_active (GTK_COMBO_BOX (netinfo->type));
98 
99 	parent = gtk_widget_get_toplevel (netinfo->output);
100 
101 	program = util_find_program_dialog ("dig", parent);
102 
103 	if (program != NULL) {
104 		use_reverse_lookup = pattern_match (host, address_regular_expression);
105 
106 		num_terms = 4;
107 		if (use_reverse_lookup)
108 			num_terms++;
109 		if (active_index > 0)
110 			num_terms++;
111 		command_options = g_strsplit (LOOKUP_OPTIONS, " ", -1);
112 		if (command_options != NULL) {
113 			for (j = 0; command_options[j] != NULL; j++)
114 				num_terms++;
115 		}
116 		command_line = g_new (gchar *, num_terms + 1);
117 		i = 0;
118 		command_line[i++] = g_strdup (program);
119 		command_line[i++] = g_strdup ("dig");
120 		if (command_options != NULL) {
121 			for (j = 0; command_options[j] != NULL; j++)
122 				command_line[i++] = g_strdup (command_options[j]);
123 		}
124 		if (use_reverse_lookup)
125 			command_line[i++] = g_strdup ("-x");
126 		command_line[i++] = g_strdup (host);
127 		if (active_index > 0)
128 			command_line[i++] = g_strdup (query_types[active_index]);
129 		command_line[i++] = NULL;
130 
131 		g_strfreev (netinfo->command_line);
132 		netinfo->command_line = command_line;
133 
134 		netinfo_process_command (netinfo);
135 
136 		g_strfreev (command_options);
137 	}
138 
139 	g_free (command);
140 	g_free (program);
141 }
142 
143 /* Process each line from lookup command */
144 void
lookup_foreach(Netinfo * netinfo,gchar * line,gssize len,gpointer user_data)145 lookup_foreach (Netinfo * netinfo, gchar * line, gssize len,
146 		gpointer user_data)
147 {
148 	gchar *text_utf8;
149 	gsize bytes_written;
150 	GtkTextBuffer *buffer = NULL;
151 	GtkTextIter iter;
152 
153 	g_return_if_fail (netinfo != NULL);
154 	g_return_if_fail (line != NULL);
155 
156 	buffer =
157 		gtk_text_view_get_buffer (GTK_TEXT_VIEW (netinfo->output));
158 	gtk_text_buffer_get_end_iter (buffer, &iter);
159 
160 	if (len > 0) {
161 		text_utf8 = g_locale_to_utf8 (line, len,
162 					      NULL, &bytes_written, NULL);
163 
164 		gtk_text_buffer_insert
165 		    (GTK_TEXT_BUFFER (buffer), &iter, text_utf8,
166 		     bytes_written);
167 		g_free (text_utf8);
168 	}
169 }
170 
171 void
lookup_foreach_with_tree(Netinfo * netinfo,gchar * line,gint len,gpointer user_data)172 lookup_foreach_with_tree (Netinfo * netinfo, gchar * line, gint len,
173 			  gpointer user_data)
174 {
175 	GtkTreeIter iter, sibling;
176 	GList *columns;
177 	GtkTreePath *path;
178 	GtkTreeModel *model;
179 	GtkTreeView *widget;
180 	gint count;
181 	lookup_data data;
182 
183 	g_return_if_fail (netinfo != NULL);
184 	g_return_if_fail (line != NULL);
185 
186 	widget = (GTK_TREE_VIEW (netinfo->output));
187 
188 	if (len > 0) {		/* there are data to show */
189 		count = strip_line (line, &data);
190 
191 		if (count == LOOKUP_NUM_ARGS) {
192 
193 			gtk_tree_view_set_rules_hint (GTK_TREE_VIEW
194 						      (widget), TRUE);
195 			columns =
196 			    gtk_tree_view_get_columns (GTK_TREE_VIEW
197 						       (widget));
198 
199 			if (g_list_length (columns) == 0) {
200 
201 				model = lookup_create_model (widget);
202 				gtk_tree_view_set_model (GTK_TREE_VIEW
203 							 (widget), model);
204 			}
205 
206 			g_list_free (columns);
207 
208 			model =
209 			    gtk_tree_view_get_model (GTK_TREE_VIEW
210 						     (widget));
211 
212 			gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget),
213 						  &path, NULL);
214 
215 			if (path != NULL) {
216 				gtk_tree_model_get_iter (model, &sibling,
217 							 path);
218 				gtk_list_store_insert_after (GTK_LIST_STORE
219 							     (model),
220 							     &iter,
221 							     &sibling);
222 			} else {
223 				gtk_list_store_append (GTK_LIST_STORE
224 						       (model), &iter);
225 			}
226 
227 			gtk_list_store_set (GTK_LIST_STORE (model), &iter,
228 					    LOOKUP_SOURCE, data.source,
229 					    LOOKUP_TTL, data.ttl,
230 					    LOOKUP_ADDR_TYPE, data.addr_type,
231 					    LOOKUP_RECORD_TYPE, data.record_type,
232 					    LOOKUP_DESTINATION, data.destination,
233 						-1);
234 
235 			gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
236 						 model);
237 			path = gtk_tree_model_get_path (model, &iter);
238 			gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget),
239 						  path, NULL, FALSE);
240 			gtk_tree_path_free (path);
241 		}
242 	}
243 }
244 
245 static gint
strip_line(gchar * line,lookup_data * data)246 strip_line (gchar * line, lookup_data * data)
247 {
248 	gint count;
249 	gchar priority[128], host_mx[128];
250 
251 	line = g_strdelimit (line, "\t\t", '\t');
252 
253 	count = sscanf (line, LOOKUP_FORMAT_MX, data->source, &(data)->ttl,
254 			        data->addr_type, priority, host_mx);
255 
256 	if (count == LOOKUP_NUM_ARGS) {
257 		g_sprintf (data->record_type, "MX");
258 		g_snprintf (data->destination, 128,"%s (%s)", host_mx, priority);
259 	} else {
260 		count = sscanf (line, LOOKUP_FORMAT,
261 				data->source, &(data)->ttl, data->addr_type,
262 				data->record_type, data->destination);
263 	}
264 
265 	return count;
266 }
267 
268 static GtkTreeModel *
lookup_create_model(GtkTreeView * widget)269 lookup_create_model (GtkTreeView *widget)
270 {
271 	GtkCellRenderer *renderer = NULL;
272 	static GtkTreeViewColumn *column;
273 	GtkTreeModel *model;
274 
275 	renderer = gtk_cell_renderer_text_new ();
276 	/* Hostname */
277 	column =
278 	    gtk_tree_view_column_new_with_attributes
279 	    (_("Name"), renderer, "text", LOOKUP_SOURCE, NULL);
280 
281 	gtk_tree_view_append_column (widget, column);
282 
283 	renderer = gtk_cell_renderer_text_new ();
284 	/* Time To Live of a hostname in a name server */
285 	column =
286 	    gtk_tree_view_column_new_with_attributes
287 		/* Time To Live of a hostname in a name server */
288 	    (_("TTL"), renderer, "text", LOOKUP_TTL, NULL);
289 	gtk_tree_view_column_set_alignment (column, 0.5);
290 	g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
291 	gtk_tree_view_append_column (widget, column);
292 
293 	renderer = gtk_cell_renderer_text_new ();
294 	/* Type of address in the resolution (name server) */
295 	column =
296 	    gtk_tree_view_column_new_with_attributes
297 	    (_("Address Type"), renderer, "text", LOOKUP_ADDR_TYPE, NULL);
298 	g_object_set (G_OBJECT (renderer), "xalign", 0.5, NULL);
299 	gtk_tree_view_column_set_alignment (column, 0.5);
300 	gtk_tree_view_append_column (widget, column);
301 
302 
303 	renderer = gtk_cell_renderer_text_new ();
304 	/* Type of record (A, HINFO, PTR, etc.) */
305 	column =
306 	    gtk_tree_view_column_new_with_attributes
307 	    (_("Record Type"), renderer, "text", LOOKUP_RECORD_TYPE, NULL);
308 
309 	gtk_tree_view_append_column (widget, column);
310 
311 
312 	renderer = gtk_cell_renderer_text_new ();
313 	/* Address/Name associated */
314 	column =
315 	    gtk_tree_view_column_new_with_attributes
316 	    (_("Address"), renderer, "text", LOOKUP_DESTINATION, NULL);
317 
318 	gtk_tree_view_append_column (widget, column);
319 
320 	model = GTK_TREE_MODEL (gtk_list_store_new
321 				(LOOKUP_NUM_COLUMNS,
322 				 G_TYPE_STRING,
323 				 G_TYPE_INT,
324 				 G_TYPE_STRING,
325 				 G_TYPE_STRING,
326 				 G_TYPE_STRING));
327 
328 	return model;
329 }
330 
331 void
lookup_copy_to_clipboard(Netinfo * netinfo,gpointer user_data)332 lookup_copy_to_clipboard (Netinfo * netinfo, gpointer user_data)
333 {
334 	GString *result, *content;
335 
336 	g_return_if_fail (netinfo != NULL);
337 
338 	/* The lookup output in text format:
339 	   Source of query (hostname/ip address),
340 	   Time To Live (TTL), Address Type,
341 	   Record Type (A, PTR, HINFO, NS, TXT, etc.),
342 	   Resolution (results of the query)
343 	   It's a tabular output, and these belongs to the column titles */
344 	result = g_string_new (_("Source\tTTL\tAddress Type\tRecord Type1\tResolution\n"));
345 
346 	content = util_tree_model_to_string (GTK_TREE_VIEW (netinfo->output));
347 
348 	g_string_append_printf (result, "%s", content->str);
349 
350 	gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE), result->str,
351 				result->len);
352 
353 	g_string_free (content, TRUE);
354 	g_string_free (result, TRUE);
355 }
356