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