writemaphtml_url -> html_url (generic).
[silc.git] / apps / silcmap / silcmap_html.c
1 /*
2
3   silcmap_html.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silcincludes.h"
21 #include "silcclient.h"
22 #include "silcmap.h"
23
24 /* Write the HTML data file of the gathered data from the connection. */
25
26 bool silc_map_writehtml(SilcMap map, SilcMapConnection mapconn)
27 {
28   FILE *fp;
29   char *hostname;
30   char filename[256];
31
32   /* Generate data filename.  First configure hostname is the filename */
33   silc_dlist_start(mapconn->hostnames);
34   hostname = silc_dlist_get(mapconn->hostnames);
35   memset(filename, 0, sizeof(filename));
36   snprintf(filename, sizeof(filename) - 1, "%s_%d.html", hostname,
37            mapconn->port);
38
39   /* Open for writing */
40   fp = fopen(filename, "w+");
41   if (!fp) {
42     fprintf(stderr, "Could not open file '%s'\n", filename);
43     return FALSE;
44   }
45
46   /* Write the HTML page */
47
48   fprintf(fp, "<!-- Automatically generated by silcmap --!>\n");
49   fprintf(fp, "<br /><hr ><br />\n");
50
51   /* General stuff */
52
53   fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n");
54   silc_dlist_start(mapconn->hostnames);
55   while ((hostname = silc_dlist_get(mapconn->hostnames)) != SILC_LIST_END)
56     fprintf(fp, "<tr><td><b>Hostname</b></td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", hostname);
57
58   silc_dlist_start(mapconn->ips);
59   while ((hostname = silc_dlist_get(mapconn->ips)) != SILC_LIST_END)
60     fprintf(fp, "<tr><td><b>IP</b></td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", hostname);
61
62   fprintf(fp, "<tr><td><b>Port</b></td><td>&nbsp;:</td><td>&nbsp;%d</td></tr>\n", mapconn->port);
63   fprintf(fp, "<tr><td><b>Country</b></td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", mapconn->country);
64   fprintf(fp, "<tr><td><b>City</b></td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", mapconn->city);
65   fprintf(fp, "<tr><td><b>Admin</b></td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", mapconn->admin);
66   fprintf(fp, "</table>\n");
67
68   /* Public key */
69   if (mapconn->public_key) {
70     SilcPublicKey public_key;
71     SilcPublicKeyIdentifier ident;
72     char *fingerprint, *babbleprint;
73     unsigned char *pk;
74     SilcUInt32 pk_len;
75     SilcPKCS pkcs;
76     SilcUInt32 key_len = 0;
77     FILE *pd;
78     unsigned char *pdd;
79
80     fprintf(fp, "&nbsp;<br /><hr ><br />\n");
81     fprintf(fp, "<b>Public Key:</b>&nbsp;<br />\n");
82     fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n");
83
84     if (silc_pkcs_load_public_key(mapconn->public_key, &public_key,
85                                   SILC_PKCS_FILE_PEM) == FALSE)
86       if (silc_pkcs_load_public_key(mapconn->public_key, &public_key,
87                                     SILC_PKCS_FILE_BIN) == FALSE) {
88         fprintf(stderr, "Could not load public key file `%s'\n",
89                 mapconn->public_key);
90         return FALSE;
91       }
92
93     ident = silc_pkcs_decode_identifier(public_key->identifier);
94     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
95     fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
96     babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
97
98     if (silc_pkcs_alloc(public_key->name, &pkcs)) {
99       key_len = silc_pkcs_public_key_set(pkcs, public_key);
100       silc_pkcs_free(pkcs);
101     }
102
103     fprintf(fp, "<tr><td>&nbsp;&nbsp;");
104     fprintf(fp, "Public key file</td><td>&nbsp;:</td><td>&nbsp;<a href=\"%s\">%s</a></td></tr>\n",
105             mapconn->public_key, mapconn->public_key);
106     fprintf(fp, "<tr><td>&nbsp;&nbsp;");
107     fprintf(fp, "Algorithm</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", public_key->name);
108     if (key_len) {
109       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
110       fprintf(fp, "Key length (bits)</td><td>&nbsp;:</td><td>&nbsp;%d</td></tr>\n", (unsigned int)key_len);
111     }
112     if (ident->realname) {
113       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
114       fprintf(fp, "Real name</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", ident->realname);
115     }
116     if (ident->username) {
117       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
118       fprintf(fp, "Username</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", ident->username);
119     }
120     if (ident->host) {
121       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
122       fprintf(fp, "Hostname</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", ident->host);
123     }
124     if (ident->email) {
125       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
126       fprintf(fp, "Email</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", ident->email);
127     }
128     if (ident->org) {
129       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
130       fprintf(fp, "Organization</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", ident->org);
131     }
132     if (ident->country) {
133       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
134       fprintf(fp, "Country</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", ident->country);
135     }
136     fprintf(fp, "<tr><td>&nbsp;&nbsp;");
137     fprintf(fp, "Fingerprint (SHA1)</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", fingerprint);
138     fprintf(fp, "<tr><td>&nbsp;&nbsp;");
139     fprintf(fp, "Babbleprint (SHA1)</td><td>&nbsp;:</td><td>&nbsp;%s</td></tr>\n", babbleprint);
140     fprintf(fp, "</table>\n");
141
142     pd = fopen(mapconn->public_key, "r");
143     if (!pd)
144       return FALSE;
145
146     pk_len = silc_file_size(mapconn->public_key);
147     pdd = silc_calloc(pk_len + 1, sizeof(*pdd));
148     if (!pdd)
149       return FALSE;
150     fread(pdd, pk_len, 1, pd);
151
152     fprintf(fp, "<pre><tt>\n");
153     fprintf(fp, "%s", pdd);
154     fprintf(fp, "</tt></pre>\n");
155
156     fclose(pd);
157     silc_free(pdd);
158     silc_free(fingerprint);
159     silc_free(babbleprint);
160     silc_free(pk);
161     silc_pkcs_public_key_free(public_key);
162     silc_pkcs_free_identifier(ident);
163   }
164
165   /* Description */
166   if (mapconn->description && mapconn->description[0]) {
167     fprintf(fp, "<hr ><br />\n");
168     fprintf(fp, "<b>Description:</b>&nbsp;<br />\n");
169     fprintf(fp, "%s<br />&nbsp;<br />\n", mapconn->description);
170   }
171
172   /* Status */
173   if (mapconn->connect) {
174     fprintf(fp, "<hr ><br />\n");
175     fprintf(fp, "<b>Server status:</b>&nbsp;<br />\n");
176     if (mapconn->down)
177       fprintf(fp,
178               "Server is currently down and unreachable. "
179               "Please try again later to connect the server.<br />\n");
180     else
181       fprintf(fp,
182               "Server is up and running<br />\n");
183   }
184
185   if (mapconn->connect && !mapconn->down) {
186     int days, hours, mins, secs, uptime;
187
188     uptime = mapconn->data.uptime;
189     days = uptime / (24 * 60 * 60);
190     uptime -= days * (24 * 60 * 60);
191     hours = uptime / (60 * 60);
192     uptime -= hours * (60 * 60);
193     mins = uptime / 60;
194     uptime -= mins * 60;
195     secs = uptime;
196
197     /* Statistics */
198     fprintf(fp, "<br />\n");
199     fprintf(fp, "<b>Server statistics:</b>&nbsp;<br />\n");
200     fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n");
201     if (mapconn->starttime) {
202       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
203       fprintf(fp, "Server start time</td><td>&nbsp;:</td><td>&nbsp;%s<td></tr>\n",
204               silc_get_time(mapconn->data.starttime));
205     }
206     if (mapconn->uptime) {
207       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
208       fprintf(fp, "Server uptime</td><td>&nbsp;:</td><td>&nbsp;%d days %d hours %d mins %d secs<td></tr>\n",
209               days, hours, mins, secs);
210     }
211     if (mapconn->clients) {
212       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
213       fprintf(fp, "Local clients</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
214               mapconn->data.clients);
215     }
216     if (mapconn->channels) {
217       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
218       fprintf(fp, "Local channels</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
219               mapconn->data.channels);
220     }
221     if (mapconn->server_ops) {
222       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
223       fprintf(fp, "Local server operators</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
224               mapconn->data.server_ops);
225     }
226     if (mapconn->router_ops) {
227       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
228       fprintf(fp, "Local router operators</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
229               mapconn->data.router_ops);
230     }
231     if (mapconn->cell_clients) {
232       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
233       fprintf(fp, "Cell clients</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
234               mapconn->data.cell_clients);
235     }
236     if (mapconn->cell_channels) {
237       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
238       fprintf(fp, "Cell channels</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
239               mapconn->data.cell_channels);
240     }
241     if (mapconn->cell_servers) {
242       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
243       fprintf(fp, "Cell servers</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
244               mapconn->data.cell_servers);
245     }
246     if (mapconn->all_clients) {
247       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
248       fprintf(fp, "All SILC clients</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
249               mapconn->data.all_clients);
250     }
251     if (mapconn->all_channels) {
252       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
253       fprintf(fp, "All SILC channels</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
254               mapconn->data.all_channels);
255     }
256     if (mapconn->all_servers) {
257       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
258       fprintf(fp, "All SILC servers</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
259               mapconn->data.all_servers);
260     }
261     if (mapconn->all_routers) {
262       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
263       fprintf(fp, "All SILC routers</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
264               mapconn->data.all_routers);
265     }
266     if (mapconn->all_server_ops) {
267       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
268       fprintf(fp, "All SILC server operators</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
269               mapconn->data.all_server_ops);
270     }
271     if (mapconn->all_router_ops) {
272       fprintf(fp, "<tr><td>&nbsp;&nbsp;");
273       fprintf(fp, "All SILC router operators</td><td>&nbsp;:</td><td>&nbsp;%ld</td></tr>\n",
274               mapconn->data.all_router_ops);
275     }
276     fprintf(fp, "</table>\n");
277   }
278
279   /* motd */
280   if (mapconn->motd) {
281     fprintf(fp, "&nbsp;<br /><hr ><br />\n");
282     fprintf(fp, "<b>Message of the Day:</b>&nbsp;<br />\n");
283     fprintf(fp, "<pre><tt>%s</tt><pre>\n", mapconn->data.motd);
284   }
285
286   fprintf(fp, "<br />\n");
287
288   fclose(fp);
289   return TRUE;
290 }
291
292 /* Write the HTML index file that lists all servers. */
293
294 bool silc_map_writehtml_index(SilcMap map)
295 {
296   SilcMapConnection mapconn;
297   char *hostname, *ip, *class;
298   FILE *fp;
299
300   /* Open for writing */
301   fp = fopen(map->writehtml.filename, "w+");
302   if (!fp) {
303     fprintf(stderr, "Could not open file '%s'\n", map->writehtml.filename);
304     return FALSE;
305   }
306
307   /* Produce a simple HTML index file of all servers */
308   class = map->writehtml.text ? map->writehtml.text : "silcmap";
309
310   fprintf(fp, "<!-- Automatically generated by silcmap --!>\n");
311   fprintf(fp, "<br />\n");
312   fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" "
313           "class=\"%s\" border=\"0\">\n", class);
314   fprintf(fp,
315           "<tr>\n"
316           "<td align=\"center\" class=\"%s_header\"><b>Hostname</b></td>\n"
317           "<td align=\"center\" class=\"%s_header\"><b>IPv4 Address</b></td>\n"
318           "<td align=\"center\" class=\"%s_header\"><b>Port</b></td>\n"
319           "<td align=\"center\" class=\"%s_header\"><b>Country</b></td>\n"
320           "<td align=\"center\" class=\"%s_header\"><b>Oper</b></td>\n"
321           "</tr>\n", class, class, class, class, class);
322
323   silc_dlist_start(map->conns);
324   while ((mapconn = silc_dlist_get(map->conns)) != SILC_LIST_END) {
325
326     silc_dlist_start(mapconn->hostnames);
327     hostname = silc_dlist_get(mapconn->hostnames);
328     silc_dlist_start(mapconn->ips);
329     ip = silc_dlist_get(mapconn->ips);
330
331     fprintf(fp,
332             "<tr>\n"
333             "<td align = \"center\" class=\"%s\">&nbsp;<a href=\"%s_%d.html\">%s</a></td>\n"
334             "<td align = \"center\" class=\"%s\">&nbsp;%s</td>\n"
335             "<td align = \"center\" class=\"%s\">&nbsp;%d</td>\n"
336             "<td align = \"center\" class=\"%s\">&nbsp;%s</td>\n"
337             "<td align = \"center\" class=\"%s\">&nbsp;%s</td>\n"
338             "</tr>\n", class,
339             mapconn->html_url ? mapconn->html_url : hostname, mapconn->port,
340             hostname, class, ip, class, mapconn->port, class,
341             mapconn->country, class, mapconn->admin);
342   }
343
344   fprintf(fp, "</table><br />\n");
345
346   return TRUE;
347 }
348
349 /* Creates a HTML map file, which can be used to allow user to click
350    URLs on the image at the specified locations. */
351
352 bool silc_map_writemaphtml(SilcMap map)
353 {
354   SilcMapConnection mapconn;
355   SilcMapCommand cmd;
356   char *hostname, url[256];
357   FILE *fp;
358   int xx , yy, w, h;
359
360   /* Open for writing */
361   fp = fopen(map->writemaphtml.filename, "w+");
362   if (!fp) {
363     fprintf(stderr, "Could not open file '%s'\n", map->writemaphtml.filename);
364     return FALSE;
365   }
366
367   /* The target may be portion of the original map, so we must make the
368      new coordinates relative to the new map. */
369   xx = map->writemaphtml.x;
370   yy = map->writemaphtml.y;
371
372   memset(url, 0, sizeof(url));
373
374   fprintf(fp, "<!-- Automatically generated by silcmap --!>\n");
375   fprintf(fp, "<br />\n");
376   fprintf(fp, "<img src=\"%s\" usemap=\"#map\" border=\"0\">\n",
377           map->writemaphtml.text);
378   fprintf(fp, "<map name=\"map\">\n");
379
380   memset(url, 0, sizeof(url));
381
382   silc_dlist_start(map->conns);
383   while ((mapconn = silc_dlist_get(map->conns)) != SILC_LIST_END) {
384     if (mapconn->html_url && mapconn->html_url[0]) {
385       silc_strncat(url, sizeof(url), mapconn->html_url,
386                    strlen(mapconn->html_url));
387     } else {
388       silc_dlist_start(mapconn->hostnames);
389       hostname = silc_dlist_get(mapconn->hostnames);
390       snprintf(url, sizeof(url) - 1, "%s_%d.html", hostname, mapconn->port);
391     }
392
393     /* Print the positions of various items on the map into the map file */
394     silc_dlist_start(mapconn->commands);
395     while ((cmd = silc_dlist_get(mapconn->commands)) != SILC_LIST_END) {
396       if (cmd->draw_text) {
397         w = strlen(cmd->text) * 5;
398         h = map->font.height - 2;
399         fprintf(fp,
400                 "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
401                 (int)(cmd->x - xx), (int)(cmd->y - yy), w, h, url);
402       }
403
404       if (cmd->draw_circle) {
405         w = 4;
406         fprintf(fp,
407                 "<area shape=\"circle\" coords=\"%d,%d,%d\" href=\"%s\">\n",
408                 (int)(cmd->x - xx), (int)(cmd->y - yy), w, url);
409         if (cmd->text) {
410           w = strlen(cmd->text) * 5;
411           h = map->font.height - 2;
412           fprintf(fp,
413                   "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
414                   (int)(cmd->x - xx + cmd->lposx),
415                   (int)(cmd->y - yy - cmd->lposy),
416                   (int)(cmd->x - xx + cmd->lposx + w),
417                   (int)(cmd->y - yy - cmd->lposy + h), url);
418         }
419       }
420
421       if (cmd->draw_rectangle) {
422         w = 7;
423         h = 6;
424         fprintf(fp,
425                 "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
426                 (int)(cmd->x - xx), (int)(cmd->y - yy),
427                 (int)(cmd->x - xx + w), (int)(cmd->y - yy + h), url);
428         if (cmd->text) {
429           w = strlen(cmd->text) * 5;
430           h = map->font.height - 2;
431           fprintf(fp,
432                   "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
433                   (int)(cmd->x - xx + cmd->lposx),
434                   (int)(cmd->y - yy - cmd->lposy),
435                   (int)(cmd->x - xx + cmd->lposx + w),
436                   (int)(cmd->y - yy - cmd->lposy + h), url);
437         }
438       }
439     }
440   }
441
442   fprintf(fp, "</map><br />\n");
443   fclose(fp);
444
445   return TRUE;
446 }