--- /dev/null
+#
+# Makefile.am
+#
+# Author: Pekka Riikonen <priikone@silcnet.org>
+#
+# Copyright (C) 2003 Pekka Riikonen
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+bin_PROGRAMS = silcmap
+
+silcmap_SOURCES = \
+ silcmap.c \
+ silcmap_bitmap.c \
+ silcmap_command.c \
+ silcmap_client.c \
+ silcmap_html.c
+
+LIBS = $(SILC_COMMON_LIBS) -lsilcclient -lsilc
+LDADD =
+
+EXTRA_DIST = *.h
+
+include $(top_srcdir)/Makefile.defines.in
--- /dev/null
+The SILC Map
+============
+
+SILC Map is a utility which can be used to visualize the topology of a
+SILC network. It can create maps which indicate the exact global position
+of the servers and it can create HTML pages out of the information it
+gathers from the servers. It is also possible to create a HTML map
+page which allows the user to click the servers on the map image to get
+more detailed information of the server. The links between the routers
+and servers can also be drawn on the map image.
+
+The HTML pages that SILC Map creates are by default crude looking. This
+is intentional feature to allow the user to easily embed the data pages
+into existing web site. This can be done for example by using PHP, server
+side includes or similar method.
+
+
+SILC Map Config File
+====================
+
+By default the SILC Map reads the silcmap.conf file. Please read the
+example silcmap.conf file to learn all the possible commands and
+configuration options you can use to alter the behavior of the SILC Map.
+
+
+Running the SILC Map
+====================
+
+After you have configured the silcmap.conf file, simply run the ./silcmap
+program. It reads the file, the source map image, creates the connections
+to SILC servers and producess the target image and HTML pages. After the
+map is created the silcmap program exits. If you want to periodically run
+the silcmap to generate maps you may create for example an at (see at(1))
+job on your local system.
+
+
+Contact
+=======
+
+Feedback and comments are welcome. Bug reports should be sent to the
+SILC development mailing list.
+
+Official SILC project web site : http://silcnet.org/
+FTP archive for SILC project : ftp://ftp.silcnet.org/
+Development mailing list address : silc-devel@lists.silcnet.org
+
--- /dev/null
+/*
+
+ data.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef DATA_H
+#define DATA_H
+
+/* Bitmap context */
+typedef struct {
+ char width;
+ char height;
+ unsigned char data[32 * 32];
+} MapBitmap;
+
+/* Circle */
+const MapBitmap silc_map_circle =
+{
+ 6, 7,
+ { 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 0
+ }
+};
+
+/* Rectangle */
+const MapBitmap silc_map_rectangle =
+{
+ 6, 7,
+ { 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1
+ }
+};
+
+#endif /* DATA_H */
--- /dev/null
+-----BEGIN SILC PUBLIC KEY-----
+AAAA/QADcnNhAGZVTj1zaWxjLW9wZXIsIEhOPXNpbGMuc2lsY25ldC5vcmcsIFJOPVNJTEM
+gUm91dGVyIEFkbWluLCBFPXNpbGMtb3BlckBzaWxjbmV0Lm9yZywgTz1TSUxDIFByb2plY3
+QsIEM9U0sAAAAEAAAAfwAAAIAhKuTYfWdQ5UxB6ICuYCO13+gFIXZne3ciTm4c0AiHUoRat
+5Pd116FhO2ktkVZC8QS6IfRso5BkaYtRyp7qsficnXxZmFH5nBctXvlZ5zFWiDLsDz6TKI0
+5ib/T9EyRblNIpzQVrJsopvrz0mYmZKxUuu/e06EbdvpoubeHj6xLQ==
+-----END SILC PUBLIC KEY-----
--- /dev/null
+/*
+
+ silcmap.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcversion.h"
+#include "silcmap.h"
+
+/* Allocates new SilcMap context and the SilcClient in it. */
+
+SilcMap silc_map_alloc(const char *conffile)
+{
+ SilcMap map = silc_calloc(1, sizeof(*map));
+ if (!map)
+ return NULL;
+
+ /* Allocate client */
+ map->client = silc_client_alloc(&silc_map_client_ops, NULL, NULL, NULL);
+ if (!map->client) {
+ silc_free(map);
+ return NULL;
+ }
+
+ map->client->username = strdup("silcmap");
+ map->client->hostname = silc_net_localhost();
+ map->client->realname = strdup("silcmap");
+
+ /* Init the client */
+ if (!silc_client_init(map->client)) {
+ silc_client_free(map->client);
+ silc_free(map);
+ return NULL;
+ }
+
+ /* Load new key pair if it exists, create if it doesn't. */
+ if (!silc_load_key_pair("silcmap.pub", "silcmap.prv", "",
+ &map->client->pkcs,
+ &map->client->public_key,
+ &map->client->private_key)) {
+ /* The keys don't exist. Let's generate us a key pair then! There's
+ nice ready routine for that too. Let's do 1024 bit RSA key pair. */
+ if (!silc_create_key_pair("rsa", 1024, "silcmap.pub",
+ "silcmap.prv", NULL, "",
+ &map->client->pkcs,
+ &map->client->public_key,
+ &map->client->private_key, FALSE)) {
+ fprintf(stderr, "Could not create new key pair");
+ silc_client_free(map->client);
+ silc_free(map);
+ return NULL;
+ }
+ }
+
+ map->conffile = strdup(conffile);
+
+ return map;
+}
+
+/* Free the SilcMap context and all data in it. */
+
+void silc_map_free(SilcMap map)
+{
+ SilcMapConnection mapconn;
+ SilcMapCommand cmd;
+ char *h;
+
+ silc_free(map->conffile);
+ silc_free(map->bitmap);
+
+ if (map->client) {
+ silc_free(map->client->username);
+ silc_free(map->client->realname);
+ silc_free(map->client->hostname);
+ silc_client_free(map->client);
+ }
+
+ if (map->conns) {
+ silc_dlist_start(map->conns);
+ while ((mapconn = silc_dlist_get(map->conns)) != SILC_LIST_END) {
+ silc_dlist_start(mapconn->hostnames);
+ while ((h = silc_dlist_get(mapconn->hostnames)) != SILC_LIST_END)
+ silc_free(h);
+ silc_dlist_uninit(mapconn->hostnames);
+
+ silc_dlist_start(mapconn->ips);
+ while ((h = silc_dlist_get(mapconn->ips)) != SILC_LIST_END)
+ silc_free(h);
+ silc_dlist_uninit(mapconn->ips);
+
+ silc_dlist_start(mapconn->commands);
+ while ((cmd = silc_dlist_get(mapconn->commands)) != SILC_LIST_END) {
+ silc_free(cmd->filename);
+ silc_free(cmd->text);
+ silc_free(cmd);
+ }
+ silc_dlist_uninit(mapconn->commands);
+
+ silc_free(mapconn->public_key);
+ silc_free(mapconn->country);
+ silc_free(mapconn->city);
+ silc_free(mapconn->admin);
+ silc_free(mapconn->description);
+ silc_free(mapconn->writemaphtml_url);
+ silc_free(mapconn->up_color);
+ silc_free(mapconn->up_text_color);
+ silc_free(mapconn->down_color);
+ silc_free(mapconn->down_text_color);
+ silc_free(mapconn->data.motd);
+ silc_free(mapconn);
+ }
+ silc_dlist_uninit(map->conns);
+ }
+
+ silc_free(map->writemap.filename);
+ silc_free(map->writehtml.filename);
+ silc_free(map->writemaphtml.filename);
+ silc_free(map->writemaphtml.text);
+ silc_free(map->cut.filename);
+
+ silc_free(map);
+}
+
+/* Starts the actual silcmap by parsing the commands script. */
+
+SILC_TASK_CALLBACK(silc_map_start)
+{
+ SilcMap map = context;
+
+ /* Load default font */
+ silc_map_load_font(map, "default.fnt");
+
+ /* Start command parsing. Most of the commands are executed when they
+ are parsed so most of the real magic happens here. */
+ if (!silc_map_commands_parse(map, map->conffile)) {
+ /* Program stops */
+ silc_schedule_stop(map->client->schedule);
+ }
+}
+
+/* Long command line options */
+static struct option long_opts[] =
+{
+ { "config-file", 1, NULL, 'f' },
+ { "debug", 2, NULL, 'd' },
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL,'V' },
+
+ { NULL, 0, NULL, 0 }
+};
+
+static void silc_map_usage(void)
+{
+ printf(""
+"Usage: silcmap [options]\n"
+"\n"
+" Generic Options:\n"
+" -f --config-file=FILE Alternate SILC Map configuration file\n"
+" -d --debug=string Enable debugging\n"
+" -h --help Display this message and exit\n"
+" -V --version Display version and exit\n"
+"\n");
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ SilcMap map;
+ int opt, option_index;
+ char *filename = NULL;
+
+ if (argc > 1) {
+ while ((opt = getopt_long(argc, argv, "f:d:hV",
+ long_opts, &option_index)) != EOF) {
+ switch(opt) {
+ case 'h':
+ silc_map_usage();
+ break;
+ case 'V':
+ printf("SILC Map, version %s\n", silc_dist_version);
+ printf("(c) 2003 Pekka Riikonen <priikone@silcnet.org>\n");
+ exit(0);
+ break;
+ case 'd':
+#ifdef SILC_DEBUG
+ silc_debug = TRUE;
+ silc_debug_hexdump = TRUE;
+ if (optarg)
+ silc_log_set_debug_string(optarg);
+ silc_log_quick = TRUE;
+#else
+ fprintf(stderr,
+ "Run-time debugging is not enabled. To enable it recompile\n"
+ "the server with --enable-debug configuration option.\n");
+#endif
+ break;
+ case 'f':
+ filename = strdup(optarg);
+ break;
+ default:
+ silc_map_usage();
+ break;
+ }
+ }
+ }
+
+ /* Allocate map context */
+ if (!filename)
+ filename = strdup("silcmap.conf");
+ map = silc_map_alloc(filename);
+ if (!map)
+ return 1;
+
+ /* Schedule for command script parsing */
+ silc_schedule_task_add(map->client->schedule, 0,
+ silc_map_start, map, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
+ /* Run the silcmap client */
+ silc_client_run(map->client);
+
+ /* Cleanup */
+ silc_client_stop(map->client);
+ silc_map_free(map);
+ silc_free(filename);
+
+ return 0;
+}
--- /dev/null
+#
+# Map drawing script file
+#
+# Command : server { ... }
+# Description : Specifies a server to connect, fetch statistics, draw the
+# server on map and to show its status on the map. See the
+# example server command below for all parameters of this
+# command.
+#
+# Command : loadmap { filename = <filename>; };
+# Example : loadmap { filename = "world_map.ppm"; };
+# Description : Load the source bitmap image file to be used as the map
+#
+# Command : writemap { filename = <filename>; };
+# Example : writemap { filename = "map.ppm"; };
+# Description : Write the target bitmap image file
+#
+# Command : writemaphtml { filename = <filename>; image = <filename>;
+# cut_lat = <lat>; cut_lon = <lon>; };
+# Example : writemaphtml { filename = "htmlmap.map"; image = "map.jpg"; };
+# Description : Write the gathered information as as HTML map page. This
+# allows the user to click the specified points of URLs.
+# The writemaphtml_url parameter in server will specify the
+# URL that will be used in the HTML map. If omitted the
+# filename created by writehml command is used. The <cut_lat>
+# and <cut_lon> are specified if the <image> is a portion of
+# the original map image. In this case the lat and lon specify
+# which portion it is.
+#
+# Command : writehtml { filename = <filename>; };
+# Example : writehtml { filename = "index.html"; };
+# Description : Write the gathered information as HTML pages. Every server
+# command will have their own HTML file. The filename is
+# based on the hostname of the server. The index HTML file
+# will include list of the servers. The generated HTML files
+# are quite raw and are intended to be embedded into user's
+# own website.
+#
+# Command : cut { lat = <lat>; lon = <lon>; width = <width>;
+# height = <height>; filename = <filename>; };
+# Example : cut { lat = "20"; lon = "5"; width = "1000"; height = "700";
+# filename = "map_chunk.ppm"; };
+# Description : Cuts a chunk from the source image at specified location.
+# The chunk will be <width> * <height> pixels in size. The
+# <filename> is the output bitmap file where the chunk is saved.
+#
+# Command : rectangle { lat = <lat>; lon = <lon>; color = <color>;
+# label = <label>; lposx = <x>; lposy = <y>;
+# lcolor = <label color>; };
+# Example : rectangle { lat = "-31 30"; lon = "0"; color = "0 0 255";
+# label = "text"; lposx = "-10", lposy = "15"; };
+# Description : Draws a rectangle at specified location. The center of the
+# rectangle will be at specified location. If the <label>
+# is specified, that text will appear with the rectangle at the
+# <lposx> and <lposy> pixel location in relation to the
+# rectangle. If <lcolor> is omitted the <color> is used.
+#
+# Command : circle { lat = <lat>; lon = <lon>; color = <color>;
+# label = <label>; lposx = <x>; lposy = <y>;
+# lcolor = <label color>; };
+# Example : circle { lat = "31 30"; lon = "0"; color = "255 255 255"; };
+# Description : Draws a circle at specified location. The center of the
+# circle will be at specified location. If the <label>
+# is specified, that text will appear with the circle at the
+# <lposx> and <lposy> pixel location in relation to the
+# circle. If <lcolor> is omitted the <color> is used.
+#
+# Command : line { a_lat = <lat>; a_lon = <lon>; b_lat = <lat>;
+# b_lon = <lon>; width = <width>; color = <color>; };
+# Description : Draws a straight line between points a and b. The <width>
+# is line width in pixels. If omitted, default is 1.
+#
+# Command : text { lat = <lat>; lon = <lon>; color = <color>;
+# text = <text>; };
+# Example : text { lat = "63 42 13", lon = "23 17 34", color = "0 0 255";
+# text = "This is an example text"; };
+# Description : Prints the text <text> at the specified location
+#
+# The <lat> is in format DD MM SS, where DD is degrees, MM minutes, and
+# SS seconds. If DD is positive the latitude is north bound, if negative
+# it is south bound. At least DD must be specified.
+#
+# The <lon> is in format DD MM SS, where DD is degrees, MM minutes, and
+# SS seconds. If DD is positive the longitude is east bound, if negative
+# it is west bound. At least DD must be specified.
+#
+# The <color> is in format RRR GGG BBB, where RRR is red, GGG green and
+# BBB blue, between 0 - 255.
+#
+
+loadmap { filename = "map.ppm"; };
+writemaphtml { filename = "map.html"; image = "map.jpg"; };
+
+server {
+ # Server details
+ hostname = "eample.server.com";
+ ip = "10.2.1.1";
+ port = "706";
+ public_key = "example.server.com_706.pub";
+ country = "Finland";
+ city = "Kuopio";
+ admin = "pekka";
+ description = "";
+
+ # Connection parameters
+ connect = false;
+ connect_timeout = "30";
+
+ # Statistics to fetch
+ starttime = true;
+ uptime = true;
+ clients = true;
+ channels = true;
+ server_ops = true;
+ router_ops = true;
+ cell_clients = true;
+ cell_channels = true;
+ cell_servers = true;
+ all_clients = true;
+ all_channels = true;
+ all_servers = true;
+ all_routers = true;
+ all_server_ops = true;
+ all_router_ops = true;
+
+ # Fetch message of the day
+ motd = true;
+
+ # Status colors when server is either up or down
+ up_color = "150 200 190";
+ down_color = "150 0 0";
+ up_text_color = "60 200 200";
+ down_text_color = "150 0 0";
+
+ # Draw this server on the map
+ rectangle { lat = "36 00"; lon = "25 00";
+ label = "example.server.com";
+ lposx = "-30"; lposy = "10"; };
+};
+
+writemap { filename = "testi2.ppm"; };
--- /dev/null
+/*
+
+ silcmap.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef SILCMAP_H
+#define SILCMAP_H
+
+/* Font context */
+typedef struct {
+ int height;
+ struct {
+ char width;
+ unsigned char data[16 * 16];
+ } font[94];
+} MapFonts;
+
+/* SilcMap command context. */
+typedef struct {
+ /* Map command datas */
+ char *filename;
+ SilcInt32 x;
+ SilcInt32 y;
+ SilcInt32 x2;
+ SilcInt32 y2;
+ SilcUInt32 width;
+ SilcUInt32 height;
+ char *text;
+ SilcInt32 lposx;
+ SilcInt32 lposy;
+
+ SilcInt16 r;
+ SilcInt16 g;
+ SilcInt16 b;
+ SilcInt16 lr;
+ SilcInt16 lg;
+ SilcInt16 lb;
+ unsigned int color_set : 1;
+ unsigned int lcolor_set : 1;
+
+ /* Command */
+ unsigned int writemap : 1;
+ unsigned int writehtml : 1;
+ unsigned int writemaphtml : 1;
+ unsigned int cut : 1;
+ unsigned int draw_line : 1;
+ unsigned int draw_text : 1;
+ unsigned int draw_circle : 1;
+ unsigned int draw_rectangle : 1;
+} *SilcMapCommand, SilcMapCommandStruct;
+
+/* The SilcMap context. */
+typedef struct {
+ /* Connection data */
+ SilcClient client; /* SILC Client context */
+ char *conffile; /* Config file name */
+ SilcDList conns; /* Connections */
+ SilcUInt32 conns_num; /* Number of created connections */
+ SilcUInt32 conn_num; /* Current number of processed connections */
+
+ /* Bitmap data */
+ unsigned char *bitmap; /* Loaded bitmap image */
+ SilcUInt32 bitsilc_map_size; /* Size of bitmap */
+ SilcUInt32 width; /* Bitmap width in pixels */
+ SilcUInt32 height; /* Bitmap height in pixels */
+ SilcUInt32 maxcolor; /* Max color value in bitmap */
+ MapFonts font; /* Current font */
+
+ /* Output methods */
+ SilcMapCommandStruct writemap;
+ SilcMapCommandStruct writehtml;
+ SilcMapCommandStruct writemaphtml;
+ SilcMapCommandStruct cut;
+} *SilcMap;
+
+/* SilcMap connecetion context. */
+typedef struct {
+ /* Server and connection details */
+ SilcDList hostnames;
+ SilcDList ips;
+ int port;
+ char *public_key;
+ char *country;
+ char *city;
+ char *admin;
+ char *description;
+ int connect_timeout;
+ char *writemaphtml_url;
+
+ /* Flags */
+ unsigned int connect : 1;
+ unsigned int starttime : 1;
+ unsigned int uptime : 1;
+ unsigned int clients : 1;
+ unsigned int channels : 1;
+ unsigned int server_ops : 1;
+ unsigned int router_ops : 1;
+ unsigned int cell_clients : 1;
+ unsigned int cell_channels : 1;
+ unsigned int cell_servers : 1;
+ unsigned int all_clients : 1;
+ unsigned int all_channels : 1;
+ unsigned int all_servers : 1;
+ unsigned int all_routers : 1;
+ unsigned int all_server_ops : 1;
+ unsigned int all_router_ops : 1;
+ unsigned int motd : 1;
+ unsigned int down : 1;
+ unsigned int stats_received : 1;
+ unsigned int motd_received : 1;
+
+ /* Gathered data */
+ struct {
+ SilcUInt32 starttime;
+ SilcUInt32 uptime;
+ SilcUInt32 clients;
+ SilcUInt32 channels;
+ SilcUInt32 server_ops;
+ SilcUInt32 router_ops;
+ SilcUInt32 cell_clients;
+ SilcUInt32 cell_channels;
+ SilcUInt32 cell_servers;
+ SilcUInt32 all_clients;
+ SilcUInt32 all_channels;
+ SilcUInt32 all_servers;
+ SilcUInt32 all_routers;
+ SilcUInt32 all_server_ops;
+ SilcUInt32 all_router_ops;
+ char *motd;
+ } data;
+
+ /* Status colors */
+ char *up_color;
+ char *down_color;
+ char *up_text_color;
+ char *down_text_color;
+
+ /* Map commands */
+ SilcDList commands;
+
+ /* Back pointers */
+ SilcMap map;
+ SilcClientConnection conn;
+} *SilcMapConnection;
+
+extern SilcClientOperations silc_map_client_ops;
+
+SilcMap silc_map_alloc(const char *conffile);
+void silc_map_free(SilcMap map);
+bool silc_map_commands_parse(SilcMap map, const char *filename);
+void silc_map_connect(SilcMap map, SilcMapConnection mapconn);
+bool silc_map_load_ppm(SilcMap map, const char *filename);
+bool silc_map_write_ppm(SilcMap map, const char *filename);
+bool silc_map_cut(SilcMap map, SilcInt32 x, SilcInt32 y,
+ SilcUInt32 width, SilcUInt32 height,
+ SilcMap *ret_map);
+bool silc_map_draw(SilcMap map,
+ SilcInt32 x, SilcInt32 y,
+ const unsigned char *bitmap,
+ SilcUInt32 width, SilcUInt32 height);
+bool silc_map_draw_raw(SilcMap map,
+ SilcInt32 x, SilcInt32 y,
+ const unsigned char *bitmap,
+ SilcUInt32 width, SilcUInt32 height,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b);
+bool silc_map_draw_line(SilcMap map, SilcUInt32 width,
+ SilcInt32 a_x, SilcInt32 a_y,
+ SilcInt32 b_x, SilcInt32 b_y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b);
+bool silc_map_draw_text(SilcMap map, const char *text,
+ SilcInt32 x, SilcInt32 y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b);
+bool silc_map_draw_circle(SilcMap map, SilcInt32 x, SilcInt32 y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b,
+ const char *label, SilcInt32 lposx, SilcInt32 lposy,
+ SilcInt16 lr, SilcInt16 lg, SilcInt16 lb);
+bool silc_map_draw_rectangle(SilcMap map, SilcInt32 x, SilcInt32 y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b,
+ const char *label, SilcInt32 lposx,
+ SilcInt32 lposy,
+ SilcInt16 lr, SilcInt16 lg, SilcInt16 lb);
+double silc_map_parse_pos(char *pos);
+int silc_map_lon2x(SilcMap map, char *latitude);
+int silc_map_lat2y(SilcMap map, char *longitude);
+bool silc_map_parse_color(const char *color,
+ SilcInt16 *r, SilcInt16 *g, SilcInt16 *b);
+bool silc_map_load_font(SilcMap map, const char *filename);
+bool silc_map_writehtml(SilcMap map, SilcMapConnection mapconn);
+bool silc_map_writehtml_index(SilcMap map);
+bool silc_map_writemaphtml(SilcMap map);
+
+#endif /* SILCMAP_H */
--- /dev/null
+/*
+
+ silcmap_bitmap.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include <math.h>
+#include "silcmap.h"
+#include "data.h"
+
+/******* Bitmap Routines *****************************************************/
+
+/* Load a bitmap file. The file is the map image that is loaded into
+ the SilcMap context. This is no perfect PPM loader. */
+
+bool silc_map_load_ppm(SilcMap map, const char *filename)
+{
+ FILE *fp;
+ char type[3];
+ int ret, retval = TRUE;
+
+ SILC_LOG_DEBUG(("Load PPM '%s'", filename));
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "fopen: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ /* Read width and height */
+ ret = fscanf(fp, "%s %ld %ld %ld ",
+ type, &map->width, &map->height, &map->maxcolor);
+ if (ret < 4) {
+ fprintf(stderr, "fscanf: %s\n", strerror(errno));
+ retval = FALSE;
+ goto out;
+ }
+
+ /* Read the picture */
+ map->bitsilc_map_size = map->width * 3 * map->height;
+ map->bitmap = silc_malloc(map->bitsilc_map_size);
+ ret = fread(map->bitmap, map->bitsilc_map_size, 1, fp);
+ if (ret < 0) {
+ fprintf(stderr, "fscanf: %s\n", strerror(errno));
+ retval = FALSE;
+ goto out;
+ }
+
+ out:
+ fclose(fp);
+ return retval;
+}
+
+/* Write the map into a bitmap file. */
+
+bool silc_map_write_ppm(SilcMap map, const char *filename)
+{
+ FILE *fp;
+ int retval = TRUE;
+ int i, k;
+
+ SILC_LOG_DEBUG(("Write PPM '%s'", filename));
+
+ fp = fopen(filename, "w+");
+ if (!fp) {
+ fprintf(stderr, "fopen: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ /* Write the header */
+ fprintf(fp, "P6 %ld %ld %ld\n", map->width, map->height, map->maxcolor);
+
+ /* Write the bitmap */
+ for (i = 0; i < map->height; i++)
+ for (k = 0; k < map->width; k++) {
+ putc(map->bitmap[i * (map->width * 3) + (k * 3) ], fp); /* R */
+ putc(map->bitmap[i * (map->width * 3) + (k * 3) + 1], fp); /* G */
+ putc(map->bitmap[i * (map->width * 3) + (k * 3) + 2], fp); /* B */
+ }
+
+ fclose(fp);
+ return retval;
+}
+
+/* Cut the map into a `width' * `height' size chunk at `x' and `y'. This
+ returns the allocated map bitmap into `ret_bitmap'. The original map
+ is not modified. */
+
+bool silc_map_cut(SilcMap map, SilcInt32 x, SilcInt32 y,
+ SilcUInt32 width, SilcUInt32 height,
+ SilcMap *ret_map)
+{
+ int i;
+
+ SILC_LOG_DEBUG(("cut"));
+
+ /* Sanity checks */
+ if (height > map->height - y) {
+ fprintf(stderr, "Requesting too much height: %ld\n", height);
+ return FALSE;
+ }
+ if (width > map->width - x) {
+ fprintf(stderr, "Requesting too much width: %ld\n", width);
+ return FALSE;
+ }
+
+ /* Compute coordinates in the bitmap */
+ y = (map->width * 3) * y;
+ x = (x * 3);
+
+ /* Allocate new SilcMap context */
+ *ret_map = silc_calloc(1, sizeof(**ret_map));
+ (*ret_map)->width = width;
+ (*ret_map)->height = height;
+ (*ret_map)->maxcolor = map->maxcolor;
+ (*ret_map)->bitsilc_map_size = (width * 3) * height;
+ (*ret_map)->bitmap = silc_malloc((*ret_map)->bitsilc_map_size);
+
+ /* Copy the requested area */
+ for (i = 0; i < height; i++) {
+ memcpy((*ret_map)->bitmap + (i * width * 3),
+ map->bitmap + y + x, width * 3);
+
+ /* Next line */
+ y += (map->width * 3);
+ }
+
+ return TRUE;
+}
+
+/* Draw a bitmap indicated by `bitmap' of size of `width' * 'height'
+ into the SilcMap context into the coordinates `x' and `y' (the upper left
+ corner of the bitmap will be at x and y). The `bitmap' must be RGB
+ color bitmap. */
+
+bool silc_map_draw(SilcMap map,
+ SilcInt32 x, SilcInt32 y,
+ const unsigned char *bitmap,
+ SilcUInt32 width, SilcUInt32 height)
+{
+ int i, k;
+ unsigned char val;
+
+ /* Compute coordinates in the bitmap */
+ y = (map->width * 3) * y;
+ x = (x * 3);
+
+ /* Draw the bitmap into the map bitmap */
+ for (i = 0; i < height; i++) {
+ for (k = 0; k < width; k++) {
+ val = bitmap[i * (width * 3) + (k * 3)];
+ map->bitmap[y + x + (k * 3) ] = val; /* R */
+
+ val = bitmap[i * (width * 3) + (k * 3) + 1];
+ map->bitmap[y + x + (k * 3) + 1] = val; /* G */
+
+ val = bitmap[i * (width * 3) + (k * 3) + 2];
+ map->bitmap[y + x + (k * 3) + 2] = val; /* B */
+ }
+
+ /* Next line */
+ y += (map->width * 3);
+ }
+
+ return TRUE;
+}
+
+/* Same as silc_map_draw but the `bitmap' is a grayscale bitmap
+ and the RGB color information is provided as argument to this function. */
+
+bool silc_map_draw_raw(SilcMap map,
+ SilcInt32 x, SilcInt32 y,
+ const unsigned char *bitmap,
+ SilcUInt32 width, SilcUInt32 height,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b)
+{
+ int i, k;
+ unsigned char val;
+
+ /* Compute coordinates in the bitmap */
+ y = (map->width * 3) * y;
+ x = (x * 3);
+
+ /* Draw the bitmap into the map bitmap */
+ for (i = 0; i < height; i++) {
+ for (k = 0; k < width; k++) {
+ val = bitmap[i * width + k];
+ if (val != 0) {
+ map->bitmap[y + x + (k * 3) ] = r; /* R */
+ map->bitmap[y + x + (k * 3) + 1] = g; /* G */
+ map->bitmap[y + x + (k * 3) + 2] = b; /* B */
+ }
+ }
+
+ /* Next line */
+ y += (map->width * 3);
+ }
+
+ return TRUE;
+}
+
+/* Draw a straight line between points a and b. The coordinates for the
+ points are provided as arguments. The `width' is the line width in
+ pixels. The RGB color for the line can be provided too. Implements
+ DDA algorithm. */
+
+bool silc_map_draw_line(SilcMap map, SilcUInt32 width,
+ SilcInt32 a_x, SilcInt32 a_y,
+ SilcInt32 b_x, SilcInt32 b_y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b)
+{
+ unsigned char p[3] = { r, g, b };
+ int xdiff, ydiff, i;
+ double x, y, slox, sloy;
+
+ SILC_LOG_DEBUG(("draw_line"));
+
+ /* Compute the difference of points */
+ xdiff = b_x - a_x;
+ ydiff = b_y - a_y;
+ if (!xdiff && !ydiff)
+ return FALSE;
+
+ /* Draw the line */
+ if (abs(xdiff) > abs(ydiff)) {
+ sloy = (double)ydiff / (double)xdiff;
+ y = a_y + 0.5; /* rounding */
+ if (xdiff > 0) {
+ for (x = a_x; x <= b_x; x++) {
+ for (i = 0; i < width; i++)
+ silc_map_draw(map, x + i, floor(y), p, 1, 1);
+ y += sloy;
+ }
+ } else {
+ for (x = a_x; x >= b_x; x--) {
+ for (i = 0; i < width; i++)
+ silc_map_draw(map, x + i, floor(y), p, 1, 1);
+ y -= sloy;
+ }
+ }
+ } else {
+ slox = (double)xdiff / (double)ydiff;
+ x = a_x + 0.5; /* rounding */
+ if (ydiff > 0) {
+ for (y = a_y; y <= b_y; y++) {
+ for (i = 0; i < width; i++)
+ silc_map_draw(map, floor(x + i), y, p, 1, 1);
+ x += slox;
+ }
+ } else {
+ for (y = a_y; y >= b_y; y--) {
+ for (i = 0; i < width; i++)
+ silc_map_draw(map, floor(x + i), y, p, 1, 1);
+ x -= slox;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* Print the text string `text' on the bitmap at `x' and `y'. The color
+ for the text can be provided as argument. */
+
+bool silc_map_draw_text(SilcMap map, const char *text,
+ SilcInt32 x, SilcInt32 y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b)
+{
+ int k, w;
+ int c;
+
+ SILC_LOG_DEBUG(("draw_text"));
+
+ /* Write the text. */
+ w = 0;
+ for (k = 0; k < strlen(text); k++) {
+ c = text[k] - 33;
+ silc_map_draw_raw(map, x + w, y,
+ map->font.font[c].data,
+ map->font.font[c].width,
+ map->font.height, r, g, b);
+ w += map->font.font[c].width;
+ }
+
+ return TRUE;
+}
+
+/* Draw circle on the bitmap map at `x' and `y'. The center of the
+ circle will be at the `x' and `y'. If the `label' is provided the
+ text will appear with the circle at `lposx' and `lposy' in relation
+ with the circle. */
+
+bool silc_map_draw_circle(SilcMap map, SilcInt32 x, SilcInt32 y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b,
+ const char *label, SilcInt32 lposx, SilcInt32 lposy,
+ SilcInt16 lr, SilcInt16 lg, SilcInt16 lb)
+{
+ bool ret;
+
+ SILC_LOG_DEBUG(("draw_circle"));
+
+ y = y - (silc_map_circle.height / 2);
+ x = x - (silc_map_circle.width / 2);
+
+ ret = silc_map_draw_raw(map, x, y,
+ silc_map_circle.data,
+ silc_map_circle.width, silc_map_circle.height,
+ r, g, b);
+ if (!ret)
+ return FALSE;
+
+ if (label)
+ ret = silc_map_draw_text(map, label, x + lposx, y - lposy, lr, lg, lb);
+
+ return ret;
+}
+
+/* Draw rectangle on the bitmap map at `x' and `y'. The center of the
+ rectangle will be at the `x' and `y'. If the `label' is provided the
+ text will appear with the circle at `lposx' and `lposy' in relation
+ with the circle. */
+
+bool silc_map_draw_rectangle(SilcMap map, SilcInt32 x, SilcInt32 y,
+ SilcInt16 r, SilcInt16 g, SilcInt16 b,
+ const char *label,
+ SilcInt32 lposx, SilcInt32 lposy,
+ SilcInt16 lr, SilcInt16 lg, SilcInt16 lb)
+{
+ bool ret;
+
+ SILC_LOG_DEBUG(("draw_rectangle"));
+
+ y = y - (silc_map_rectangle.height / 2);
+ x = x - (silc_map_rectangle.width / 2);
+
+ ret = silc_map_draw_raw(map, x, y,
+ silc_map_rectangle.data, silc_map_rectangle.width,
+ silc_map_rectangle.height,
+ r, g, b);
+ if (!ret)
+ return FALSE;
+
+ if (label)
+ ret = silc_map_draw_text(map, label, x + lposx, y - lposy, lr, lg, lb);
+
+ return ret;
+}
+
+/* Parses the degree position string. For example, longitude 40 23 10,
+ as in 40 degrees, 23 minutes and 10 seconds east. Negative degree is to
+ West. For latitude positive is north and negative south. */
+
+double silc_map_parse_pos(char *pos)
+{
+ double d = 0, m = 0, s = 0;
+ int ret;
+
+ ret = sscanf(pos, "%lf %lf %lf", &d, &m, &s);
+ if (ret < 1) {
+ fprintf(stderr, "Malfromed position string '%s'\n", pos);
+ return 0;
+ }
+
+ return ((d < 0 ? -1 : d > 0 ? 1 : 0) *
+ abs(d) + (m / 60) + (s / 3600));
+}
+
+/* Converts longitude into position in the bitmap */
+
+int silc_map_lon2x(SilcMap map, char *longitude)
+{
+ double meridian, aspmul, lon;
+
+ /* Parse position string */
+ lon = silc_map_parse_pos(longitude);
+
+ /* Compute "aspect ratio multiplier" to get the position in the map. */
+ meridian = (double)map->width / (double)2.0;
+ aspmul = meridian / 180.0;
+
+ /* Compute the position in the bitmap map */
+ return (int)(double)(meridian + (lon * aspmul));
+}
+
+/* Converts latitude into position in the bitmap */
+
+int silc_map_lat2y(SilcMap map, char *latitude)
+{
+ double meridian, aspmul, lat;
+
+ /* Parse position string */
+ lat = silc_map_parse_pos(latitude);
+
+ /* Compute "aspect ratio multiplier" to get the position in the map. */
+ meridian = (double)map->height / (double)2.0;
+ aspmul = meridian / 90.0;
+
+ /* Compute the position in the bitmap map */
+ return (int)(double)(meridian - (lat * aspmul));
+}
+
+/* Parses RGB color string. */
+
+bool silc_map_parse_color(const char *color,
+ SilcInt16 *r, SilcInt16 *g, SilcInt16 *b)
+{
+ int ret;
+ int rr, gg, bb;
+
+ ret = sscanf(color, "%d %d %d", &rr, &gg, &bb);
+ if (ret < 3) {
+ fprintf(stderr, "Invalid color string: %s\n", color);
+ return FALSE;
+ }
+
+ *r = (SilcInt16)rr;
+ *g = (SilcInt16)gg;
+ *b = (SilcInt16)bb;
+
+ return TRUE;
+}
+
+/* Loads a font file. The font file format is the following:
+
+ height\n
+ width
+ font data
+ width
+ font data
+ etc.
+
+ If this function is called multiple times the new font replaces the
+ old font. */
+
+bool silc_map_load_font(SilcMap map, const char *filename)
+{
+ FILE *fp;
+ int i, x, y;
+
+ /* Load the file */
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "fopen: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ /* Read the font height */
+ i = fscanf(fp, "%d\n", &map->font.height);
+ if (i < 1)
+ return FALSE;
+
+ /* Read the font data */
+ for (i = 0; i < 94; i++) {
+ map->font.font[i].width = fgetc(fp);
+
+ for (y = 0; y < map->font.height; y++)
+ for (x = 0; x < map->font.font[i].width; x++)
+ map->font.font[i].data[(y * map->font.font[i].width) + x] = fgetc(fp);
+ }
+
+ return TRUE;
+}
--- /dev/null
+/*
+
+ silcmap_client.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcmap.h"
+
+/******* Map Client Routines *************************************************/
+
+SILC_TASK_CALLBACK(silc_map_process_done)
+{
+ SilcMap map = context;
+
+ /* Program stops */
+ silc_schedule_stop(map->client->schedule);
+}
+
+/* This function processes the data that was gathered from the server
+ and producess the outputs and the map. */
+
+void silc_map_process_data(SilcMap map, SilcMapConnection mapconn)
+{
+ SilcMapCommand cmd;
+ SilcMap ret_map;
+ SilcInt16 r, g, b, lr, lg, lb;
+
+ map->conn_num++;
+ SILC_LOG_DEBUG(("Processing the data from server (%d/%d)",
+ map->conn_num, map->conns_num));
+
+ /* Change colors according to server status */
+ silc_map_parse_color(mapconn->up_color, &r, &g, &b);
+ silc_map_parse_color(mapconn->up_text_color, &lr, &lg, &lb);
+ if (mapconn->down) {
+ silc_map_parse_color(mapconn->down_color, &r, &g, &b);
+ silc_map_parse_color(mapconn->down_text_color, &lr, &lg, &lb);
+ }
+
+ /* Execute the map commands */
+ silc_dlist_start(mapconn->commands);
+ while ((cmd = silc_dlist_get(mapconn->commands)) != SILC_LIST_END) {
+ if (cmd->cut) {
+ if (silc_map_cut(map, cmd->x, cmd->y, cmd->width,
+ cmd->height, &ret_map)) {
+ silc_map_write_ppm(ret_map, cmd->filename);
+ silc_map_free(ret_map);
+ }
+ continue;
+ }
+
+ if (cmd->draw_line) {
+ if (cmd->color_set) {
+ r = cmd->r;
+ g = cmd->g;
+ b = cmd->b;
+ }
+ silc_map_draw_line(map, cmd->width, cmd->x, cmd->y, cmd->x2, cmd->y2,
+ r, g, b);
+ continue;
+ }
+
+ if (cmd->draw_text) {
+ if (cmd->color_set) {
+ lr = cmd->r;
+ lg = cmd->g;
+ lb = cmd->b;
+ }
+ silc_map_draw_text(map, cmd->text, cmd->x, cmd->y, lr, lg, lb);
+
+ continue;
+ }
+
+ if (cmd->draw_circle) {
+ if (cmd->color_set) {
+ r = cmd->r;
+ g = cmd->g;
+ b = cmd->b;
+ }
+ if (cmd->lcolor_set) {
+ lr = cmd->lr;
+ lg = cmd->lg;
+ lb = cmd->lb;
+ }
+ silc_map_draw_circle(map, cmd->x, cmd->y, r, g, b,
+ cmd->text, cmd->lposx, cmd->lposy, lr, lg, lb);
+ continue;
+ }
+
+ if (cmd->draw_rectangle) {
+ if (cmd->color_set) {
+ r = cmd->r;
+ g = cmd->g;
+ b = cmd->b;
+ }
+ if (cmd->lcolor_set) {
+ lr = cmd->lr;
+ lg = cmd->lg;
+ lb = cmd->lb;
+ }
+ silc_map_draw_rectangle(map, cmd->x, cmd->y, r, g, b,
+ cmd->text, cmd->lposx, cmd->lposy, lr, lg, lb);
+ continue;
+ }
+
+ }
+
+ /* Write the html data file */
+ if (map->writehtml.writehtml)
+ silc_map_writehtml(map, mapconn);
+
+ /* If this was last connection, we are done and ready to quit. */
+ if (map->conn_num == map->conns_num) {
+ SILC_LOG_DEBUG(("All connections processed"));
+
+ /* Produce output */
+ if (map->writemap.writemap)
+ silc_map_write_ppm(map, map->writemap.filename);
+ if (map->cut.cut) {
+ if (silc_map_cut(map, map->cut.x, map->cut.y, map->cut.width,
+ map->cut.height, &ret_map)) {
+ silc_map_write_ppm(ret_map, map->cut.filename);
+ silc_map_free(ret_map);
+ }
+ }
+
+ /* Write the HTML index file */
+ if (map->writehtml.writehtml)
+ silc_map_writehtml_index(map);
+
+ /* Write the HTML map file */
+ if (map->writemaphtml.writemaphtml)
+ silc_map_writemaphtml(map);
+
+ /* Schedule to stop */
+ silc_schedule_task_add(map->client->schedule, 0,
+ silc_map_process_done, map, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ }
+}
+
+/* Timeout callback to detect if server is down. */
+
+SILC_TASK_CALLBACK(silc_map_connect_timeout)
+{
+ SilcMapConnection mapconn = context;
+
+ SILC_LOG_DEBUG(("Connection timeout"));
+
+ /* The server is down. */
+ mapconn->down = TRUE;
+
+ /* Continue to produce the data and the map. */
+ silc_map_process_data(mapconn->map, mapconn);
+}
+
+/* Close connection to server */
+
+SILC_TASK_CALLBACK(silc_map_connect_close)
+{
+ SilcMapConnection mapconn = context;
+
+ SILC_LOG_DEBUG(("Closing connection to %s:%d", mapconn->conn->remote_host,
+ mapconn->conn->remote_port));
+
+ silc_client_close_connection(mapconn->conn->client, mapconn->conn);
+
+ /* Continue to produce the data and the map. */
+ silc_map_process_data(mapconn->map, mapconn);
+}
+
+/* Create connection to remote server to gather information about it. */
+
+void silc_map_connect(SilcMap map, SilcMapConnection mapconn)
+{
+ char *ip;
+
+ if (!mapconn->connect) {
+ silc_schedule_task_add(map->client->schedule, 0,
+ silc_map_connect_timeout, mapconn, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ return;
+ }
+
+ /* First configure IP is used to connect. */
+ silc_dlist_start(mapconn->ips);
+ ip = silc_dlist_get(mapconn->ips);
+
+ SILC_LOG_DEBUG(("Creating connection to server %s:%d", ip, mapconn->port));
+
+ /* Create connection. We'll continue in the silc_connected after
+ connection is created. */
+ silc_client_connect_to_server(map->client, NULL,
+ mapconn->port, ip, mapconn);
+
+ /* Set connect timeout to detect if the server is down. */
+ silc_schedule_task_add(map->client->schedule, 0,
+ silc_map_connect_timeout, mapconn,
+ mapconn->connect_timeout, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+}
+
+
+/******* SILC Client Operations **********************************************/
+
+/* "say" client operation is a message from the client library to the
+ application. It may include error messages or something else. We
+ just dump them to screen. */
+
+static void
+silc_say(SilcClient client, SilcClientConnection conn,
+ SilcClientMessageType type, char *msg, ...)
+{
+
+}
+
+
+/* Message for a channel. The `sender' is the sender of the message
+ The `channel' is the channel. The `message' is the message. Note
+ that `message' maybe NULL. The `flags' indicates message flags
+ and it is used to determine how the message can be interpreted
+ (like it may tell the message is multimedia message). */
+
+static void
+silc_channel_message(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry sender, SilcChannelEntry channel,
+ SilcMessagePayload payload,
+ SilcMessageFlags flags, const unsigned char *message,
+ SilcUInt32 message_len)
+{
+
+}
+
+
+/* Private message to the client. The `sender' is the sender of the
+ message. The message is `message'and maybe NULL. The `flags'
+ indicates message flags and it is used to determine how the message
+ can be interpreted (like it may tell the message is multimedia
+ message). */
+
+static void
+silc_private_message(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry sender, SilcMessagePayload payload,
+ SilcMessageFlags flags,
+ const unsigned char *message,
+ SilcUInt32 message_len)
+{
+
+}
+
+
+/* Notify message to the client. The notify arguments are sent in the
+ same order as servers sends them. The arguments are same as received
+ from the server except for ID's. If ID is received application receives
+ the corresponding entry to the ID. For example, if Client ID is received
+ application receives SilcClientEntry. Also, if the notify type is
+ for channel the channel entry is sent to application (even if server
+ does not send it because client library gets the channel entry from
+ the Channel ID in the packet's header). */
+
+static void
+silc_notify(SilcClient client, SilcClientConnection conn,
+ SilcNotifyType type, ...)
+{
+
+}
+
+
+/* Command handler. This function is called always in the command function.
+ If error occurs it will be called as well. `conn' is the associated
+ client connection. `cmd_context' is the command context that was
+ originally sent to the command. `success' is FALSE if error occurred
+ during command. `command' is the command being processed. It must be
+ noted that this is not reply from server. This is merely called just
+ after application has called the command. Just to tell application
+ that the command really was processed. */
+
+static void
+silc_command(SilcClient client, SilcClientConnection conn,
+ SilcClientCommandContext cmd_context, bool success,
+ SilcCommand command, SilcStatus status)
+{
+
+}
+
+
+/* Command reply handler. This function is called always in the command reply
+ function. If error occurs it will be called as well. Normal scenario
+ is that it will be called after the received command data has been parsed
+ and processed. The function is used to pass the received command data to
+ the application.
+
+ `conn' is the associated client connection. `cmd_payload' is the command
+ payload data received from server and it can be ignored. It is provided
+ if the application would like to re-parse the received command data,
+ however, it must be noted that the data is parsed already by the library
+ thus the payload can be ignored. `success' is FALSE if error occurred.
+ In this case arguments are not sent to the application. The `status' is
+ the command reply status server returned. The `command' is the command
+ reply being processed. The function has variable argument list and each
+ command defines the number and type of arguments it passes to the
+ application (on error they are not sent). */
+
+static void
+silc_command_reply(SilcClient client, SilcClientConnection conn,
+ SilcCommandPayload cmd_payload, bool success,
+ SilcCommand command, SilcStatus status, ...)
+{
+ SilcMapConnection mapconn = conn->context;
+ va_list va;
+
+ /* If error occurred in client library with our command, print the error */
+ if (status != SILC_STATUS_OK)
+ fprintf(stderr, "COMMAND REPLY %s: %s\n",
+ silc_get_command_name(command),
+ silc_get_status_message(status));
+
+ if (!success)
+ return;
+
+ va_start(va, status);
+
+ switch (command) {
+ case SILC_COMMAND_STATS:
+ {
+ unsigned char *stats = va_arg(va, unsigned char *);
+ SilcUInt32 stats_len = va_arg(va, SilcUInt32);
+ SilcBufferStruct buf;
+
+ SILC_LOG_DEBUG(("STATS command reply"));
+
+ /* Get statistics structure */
+ silc_buffer_set(&buf, stats, stats_len);
+ silc_buffer_unformat(&buf,
+ SILC_STR_UI_INT(&mapconn->data.starttime),
+ SILC_STR_UI_INT(&mapconn->data.uptime),
+ SILC_STR_UI_INT(&mapconn->data.clients),
+ SILC_STR_UI_INT(&mapconn->data.channels),
+ SILC_STR_UI_INT(&mapconn->data.server_ops),
+ SILC_STR_UI_INT(&mapconn->data.router_ops),
+ SILC_STR_UI_INT(&mapconn->data.cell_clients),
+ SILC_STR_UI_INT(&mapconn->data.cell_channels),
+ SILC_STR_UI_INT(&mapconn->data.cell_servers),
+ SILC_STR_UI_INT(&mapconn->data.all_clients),
+ SILC_STR_UI_INT(&mapconn->data.all_channels),
+ SILC_STR_UI_INT(&mapconn->data.all_servers),
+ SILC_STR_UI_INT(&mapconn->data.all_routers),
+ SILC_STR_UI_INT(&mapconn->data.all_server_ops),
+ SILC_STR_UI_INT(&mapconn->data.all_router_ops),
+ SILC_STR_END);
+
+ mapconn->stats_received = TRUE;
+ }
+ break;
+
+ case SILC_COMMAND_MOTD:
+ {
+ char *motd = va_arg(va, char *);
+
+ SILC_LOG_DEBUG(("MOTD command reply"));
+
+ mapconn->data.motd = strdup(motd);
+ mapconn->motd_received = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ };
+
+ va_end(va);
+
+ if (mapconn->motd && !mapconn->motd_received)
+ return;
+ if (!mapconn->stats_received)
+ return;
+
+ /* All data is gathered, time to disconnect from the server. */
+ silc_schedule_task_add(client->schedule, 0,
+ silc_map_connect_close, mapconn, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+}
+
+
+/* Called to indicate that connection was either successfully established
+ or connecting failed. This is also the first time application receives
+ the SilcClientConnection objecet which it should save somewhere.
+ If the `success' is FALSE the application must always call the function
+ silc_client_close_connection. */
+
+static void
+silc_connected(SilcClient client, SilcClientConnection conn,
+ SilcClientConnectionStatus status)
+{
+ SilcMapConnection mapconn = conn->context;
+ SilcMap map = mapconn->map;
+
+ silc_schedule_task_del_by_context(client->schedule, mapconn);
+
+ if (status == SILC_CLIENT_CONN_ERROR) {
+ fprintf(stderr, "Could not connect to server\n");
+ silc_client_close_connection(client, conn);
+
+ /* Mark that this server is down. */
+ silc_schedule_task_add(map->client->schedule, 0,
+ silc_map_connect_timeout, mapconn, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ return;
+ }
+
+ if (mapconn->down) {
+ /* Already timeouted */
+ silc_client_close_connection(client, conn);
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Connected to server %s:%d", conn->remote_host,
+ conn->remote_port));
+
+ mapconn->conn = conn;
+
+ /* Get statistics */
+ silc_client_command_call(client, conn, "STATS");
+
+ /* Get motd if requested */
+ if (mapconn->motd) {
+ char motd[256];
+ char *hostname;
+ silc_dlist_start(mapconn->hostnames);
+ hostname = silc_dlist_get(mapconn->hostnames);
+ memset(motd, 0, sizeof(motd));
+ silc_strncat(motd, sizeof(motd), "MOTD ", 5);
+ silc_strncat(motd, sizeof(motd), hostname, strlen(hostname));
+ silc_client_command_call(client, conn, motd);
+ }
+}
+
+
+/* Called to indicate that connection was disconnected to the server.
+ The `status' may tell the reason of the disconnection, and if the
+ `message' is non-NULL it may include the disconnection message
+ received from server. */
+
+static void
+silc_disconnected(SilcClient client, SilcClientConnection conn,
+ SilcStatus status, const char *message)
+{
+ SilcMapConnection mapconn = conn->context;
+
+ silc_schedule_task_del_by_context(client->schedule, mapconn);
+
+ SILC_LOG_DEBUG(("Disconnected from server %s:%d", conn->remote_host,
+ conn->remote_port));
+
+ mapconn->conn = NULL;
+}
+
+
+/* Find authentication method and authentication data by hostname and
+ port. The hostname may be IP address as well. When the authentication
+ method has been resolved the `completion' callback with the found
+ authentication method and authentication data is called. The `conn'
+ may be NULL. */
+
+static void
+silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+ char *hostname, SilcUInt16 port,
+ SilcGetAuthMeth completion,
+ void *context)
+{
+ /* No auth */
+ completion(TRUE, SILC_AUTH_NONE, NULL, 0, context);
+}
+
+
+/* Verifies received public key. The `conn_type' indicates which entity
+ (server, client etc.) has sent the public key. If user decides to trust
+ the application may save the key as trusted public key for later
+ use. The `completion' must be called after the public key has been
+ verified. */
+
+static void
+silc_verify_public_key(SilcClient client, SilcClientConnection conn,
+ SilcSocketType conn_type, unsigned char *pk,
+ SilcUInt32 pk_len, SilcSKEPKType pk_type,
+ SilcVerifyPublicKey completion, void *context)
+{
+ /* Accept all keys without verification */
+ completion(TRUE, context);
+}
+
+
+/* Ask (interact, that is) a passphrase from user. The passphrase is
+ returned to the library by calling the `completion' callback with
+ the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
+ if not then the library will attempt to encode. */
+
+static void
+silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
+ SilcAskPassphrase completion, void *context)
+{
+ completion(NULL, 0, context);
+}
+
+
+/* Notifies application that failure packet was received. This is called
+ if there is some protocol active in the client. The `protocol' is the
+ protocol context. The `failure' is opaque pointer to the failure
+ indication. Note, that the `failure' is protocol dependant and
+ application must explicitly cast it to correct type. Usually `failure'
+ is 32 bit failure type (see protocol specs for all protocol failure
+ types). */
+
+static void
+silc_failure(SilcClient client, SilcClientConnection conn,
+ SilcProtocol protocol, void *failure)
+{
+ fprintf(stderr, "Connecting failed (protocol failure)\n");
+}
+
+
+/* Asks whether the user would like to perform the key agreement protocol.
+ This is called after we have received an key agreement packet or an
+ reply to our key agreement packet. This returns TRUE if the user wants
+ the library to perform the key agreement protocol and FALSE if it is not
+ desired (application may start it later by calling the function
+ silc_client_perform_key_agreement). If TRUE is returned also the
+ `completion' and `context' arguments must be set by the application. */
+
+static bool
+silc_key_agreement(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry client_entry, const char *hostname,
+ SilcUInt16 port, SilcKeyAgreementCallback *completion,
+ void **context)
+{
+ return FALSE;
+}
+
+
+/* Notifies application that file transfer protocol session is being
+ requested by the remote client indicated by the `client_entry' from
+ the `hostname' and `port'. The `session_id' is the file transfer
+ session and it can be used to either accept or reject the file
+ transfer request, by calling the silc_client_file_receive or
+ silc_client_file_close, respectively. */
+
+static void
+silc_ftp(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry client_entry, SilcUInt32 session_id,
+ const char *hostname, SilcUInt16 port)
+{
+
+}
+
+
+/* Delivers SILC session detachment data indicated by `detach_data' to the
+ application. If application has issued SILC_COMMAND_DETACH command
+ the client session in the SILC network is not quit. The client remains
+ in the network but is detached. The detachment data may be used later
+ to resume the session in the SILC Network. The appliation is
+ responsible of saving the `detach_data', to for example in a file.
+
+ The detachment data can be given as argument to the functions
+ silc_client_connect_to_server, or silc_client_add_connection when
+ creating connection to remote server, inside SilcClientConnectionParams
+ structure. If it is provided the client library will attempt to resume
+ the session in the network. After the connection is created
+ successfully, the application is responsible of setting the user
+ interface for user into the same state it was before detaching (showing
+ same channels, channel modes, etc). It can do this by fetching the
+ information (like joined channels) from the client library. */
+
+static void
+silc_detach(SilcClient client, SilcClientConnection conn,
+ const unsigned char *detach_data, SilcUInt32 detach_data_len)
+{
+
+}
+
+/* This structure and all the functions were taken from the
+ lib/silcclient/client_ops_example.c. */
+SilcClientOperations silc_map_client_ops = {
+ silc_say,
+ silc_channel_message,
+ silc_private_message,
+ silc_notify,
+ silc_command,
+ silc_command_reply,
+ silc_connected,
+ silc_disconnected,
+ silc_get_auth_method,
+ silc_verify_public_key,
+ silc_ask_passphrase,
+ silc_failure,
+ silc_key_agreement,
+ silc_ftp,
+ silc_detach
+};
--- /dev/null
+/*
+
+ silcmap_command.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcmap.h"
+
+/******* Command Script Parsing **********************************************/
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_server);
+SILC_CONFIG_CALLBACK(silc_map_cmd_loadmap);
+SILC_CONFIG_CALLBACK(silc_map_cmd_writemap);
+SILC_CONFIG_CALLBACK(silc_map_cmd_writemaphtml);
+SILC_CONFIG_CALLBACK(silc_map_cmd_writehtml);
+SILC_CONFIG_CALLBACK(silc_map_cmd_cut);
+SILC_CONFIG_CALLBACK(silc_map_cmd_rectangle);
+SILC_CONFIG_CALLBACK(silc_map_cmd_circle);
+SILC_CONFIG_CALLBACK(silc_map_cmd_line);
+SILC_CONFIG_CALLBACK(silc_map_cmd_text);
+
+static const SilcConfigTable silc_map_table_loadmap[] =
+{
+ { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_loadmap, NULL },
+};
+
+static const SilcConfigTable silc_map_table_writemap[] =
+{
+ { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_writemap, NULL },
+};
+
+static const SilcConfigTable silc_map_table_writemaphtml[] =
+{
+ { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_writemaphtml, NULL },
+ { "image", SILC_CONFIG_ARG_STR, silc_map_cmd_writemaphtml, NULL },
+ { "cut_lat", SILC_CONFIG_ARG_STRE, silc_map_cmd_writemaphtml, NULL },
+ { "cut_lon", SILC_CONFIG_ARG_STRE, silc_map_cmd_writemaphtml, NULL },
+};
+
+static const SilcConfigTable silc_map_table_writehtml[] =
+{
+ { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_writehtml, NULL },
+};
+
+static const SilcConfigTable silc_map_table_cut[] =
+{
+ { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_cut, NULL },
+ { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_cut, NULL },
+ { "width", SILC_CONFIG_ARG_INT, silc_map_cmd_cut, NULL },
+ { "height", SILC_CONFIG_ARG_INT, silc_map_cmd_cut, NULL },
+ { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_cut, NULL },
+};
+
+static const SilcConfigTable silc_map_table_rectangle[] =
+{
+ { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
+ { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
+ { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
+ { "label", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
+ { "lposx", SILC_CONFIG_ARG_INT, silc_map_cmd_rectangle, NULL },
+ { "lposy", SILC_CONFIG_ARG_INT, silc_map_cmd_rectangle, NULL },
+ { "lcolor", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
+};
+
+static const SilcConfigTable silc_map_table_circle[] =
+{
+ { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
+ { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
+ { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
+ { "label", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
+ { "lposx", SILC_CONFIG_ARG_INT, silc_map_cmd_circle, NULL },
+ { "lposy", SILC_CONFIG_ARG_INT, silc_map_cmd_circle, NULL },
+ { "lcolor", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
+};
+
+static const SilcConfigTable silc_map_table_line[] =
+{
+ { "a_lat", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
+ { "a_lon", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
+ { "b_lat", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
+ { "b_lon", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
+ { "width", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
+ { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
+};
+
+static const SilcConfigTable silc_map_table_text[] =
+{
+ { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
+ { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
+ { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
+ { "text", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
+};
+
+static const SilcConfigTable silc_map_table_server[] =
+{
+ /* Details */
+ { "hostname", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "ip", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "port", SILC_CONFIG_ARG_INT, silc_map_cmd_server, NULL },
+ { "public_key", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "country", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "city", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "admin", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "description", SILC_CONFIG_ARG_STRE, silc_map_cmd_server, NULL },
+ { "writemaphtml_url", SILC_CONFIG_ARG_STRE, silc_map_cmd_server, NULL },
+
+ /* Connect params */
+ { "connect", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "connect_timeout", SILC_CONFIG_ARG_INT, silc_map_cmd_server, NULL },
+
+ /* Statistics */
+ { "starttime", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "uptime", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "clients", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "channels", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "server_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "router_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "cell_clients", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "cell_channels", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "cell_servers", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "all_clients", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "all_channels", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "all_servers", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "all_routers", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "all_server_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "all_router_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+ { "motd", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
+
+ /* Colors */
+ { "up_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "down_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "up_text_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+ { "down_text_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
+
+ /* Map commands */
+ { "cut", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_cut, silc_map_table_cut },
+ { "rectangle", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_rectangle, silc_map_table_rectangle },
+ { "circle", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_circle, silc_map_table_circle },
+ { "line", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_line, silc_map_table_line },
+ { "text", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_text, silc_map_table_text },
+};
+
+static const SilcConfigTable silc_map_table_main[] =
+{
+ { "server", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_server, silc_map_table_server },
+ { "loadmap", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_loadmap, silc_map_table_loadmap },
+ { "writemap", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_writemap, silc_map_table_writemap },
+ { "writemaphtml", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_writemaphtml, silc_map_table_writemaphtml },
+ { "writehtml", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_writehtml, silc_map_table_writehtml },
+ { "cut", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_cut, silc_map_table_cut },
+ { "rectangle", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_rectangle, silc_map_table_rectangle },
+ { "circle", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_circle, silc_map_table_circle },
+ { "line", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_line, silc_map_table_line },
+ { "text", SILC_CONFIG_ARG_BLOCK,
+ silc_map_cmd_text, silc_map_table_text },
+ { NULL },
+};
+
+/* Command datas. Used when command is outside server { } section. */
+static char *filename = NULL;
+static char *lat = NULL;
+static char *lon = NULL;
+static char *lat2 = NULL;
+static char *lon2 = NULL;
+static SilcUInt32 width = 0;
+static SilcUInt32 height = 0;
+static SilcInt16 r = 0;
+static SilcInt16 g = 0;
+static SilcInt16 b = 0;
+static SilcInt16 lr = -1;
+static SilcInt16 lg = -1;
+static SilcInt16 lb = -1;
+static char *text = NULL;
+static SilcInt32 lposx = 0;
+static SilcInt32 lposy = 0;
+static bool color_set = FALSE;
+static bool lcolor_set = FALSE;
+
+/* Current server section. */
+SilcMapConnection curr_conn = NULL;
+
+/* Command: server, performs the connection to the remote server and
+ gathers statistical information. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_server)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+
+ if (!map->bitmap) {
+ fprintf(stderr, "You must call loadmap command before server command\n");
+ return SILC_CONFIG_ESILENT;
+ }
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ SILC_LOG_DEBUG(("Server config parsed"));
+
+ if (!curr_conn->ips) {
+ fprintf(stderr, "IP must be configured\n");
+ return SILC_CONFIG_EMISSFIELDS;
+ }
+ if (!curr_conn->hostnames) {
+ fprintf(stderr, "Hostname must be configured\n");
+ return SILC_CONFIG_EMISSFIELDS;
+ }
+ if (!curr_conn->port) {
+ fprintf(stderr, "Port must be configured\n");
+ return SILC_CONFIG_EMISSFIELDS;
+ }
+
+ /* The server data is now gathered. We continue by creating the
+ connection to the server and executing the requested commands. */
+ silc_map_connect(map, curr_conn);
+ map->conns_num++;
+
+ /* Cleanup */
+ curr_conn = NULL;
+
+ return retval;
+ }
+
+ /* Mark the current parsed server */
+ if (!curr_conn) {
+ curr_conn = silc_calloc(1, sizeof(*curr_conn));
+ if (!curr_conn)
+ return SILC_CONFIG_ESILENT;
+
+ curr_conn->hostnames = silc_dlist_init();
+ curr_conn->ips = silc_dlist_init();
+ curr_conn->commands = silc_dlist_init();
+ curr_conn->map = map;
+ if (!map->conns)
+ map->conns = silc_dlist_init();
+ silc_dlist_add(map->conns, curr_conn);
+ }
+
+ if (!strcmp(name, "hostname")) {
+ silc_dlist_add(curr_conn->hostnames, strdup((char *)val));
+ } else if (!strcmp(name, "ip")) {
+ silc_dlist_add(curr_conn->ips, strdup((char *)val));
+ } else if (!strcmp(name, "port")) {
+ curr_conn->port = (SilcUInt32)*(int *)val;
+ } else if (!strcmp(name, "public_key")) {
+ curr_conn->public_key = strdup((char *)val);
+ } else if (!strcmp(name, "country")) {
+ curr_conn->country = strdup((char *)val);
+ } else if (!strcmp(name, "city")) {
+ curr_conn->city = strdup((char *)val);
+ } else if (!strcmp(name, "admin")) {
+ curr_conn->admin = strdup((char *)val);
+ } else if (!strcmp(name, "description")) {
+ curr_conn->description = strdup((char *)val);
+ } else if (!strcmp(name, "writemaphtml_url")) {
+ curr_conn->writemaphtml_url = strdup((char *)val);
+ } else if (!strcmp(name, "connect")) {
+ curr_conn->connect = (bool)*(int *)val;
+ } else if (!strcmp(name, "connect_timeout")) {
+ curr_conn->connect_timeout = (SilcUInt32)*(int *)val;
+ } else if (!strcmp(name, "starttime")) {
+ curr_conn->starttime = (bool)*(int *)val;
+ } else if (!strcmp(name, "uptime")) {
+ curr_conn->uptime = (bool)*(int *)val;
+ } else if (!strcmp(name, "clients")) {
+ curr_conn->clients = (bool)*(int *)val;
+ } else if (!strcmp(name, "channels")) {
+ curr_conn->channels = (bool)*(int *)val;
+ } else if (!strcmp(name, "server_ops")) {
+ curr_conn->server_ops = (bool)*(int *)val;
+ } else if (!strcmp(name, "router_ops")) {
+ curr_conn->router_ops = (bool)*(int *)val;
+ } else if (!strcmp(name, "cell_clients")) {
+ curr_conn->cell_clients = (bool)*(int *)val;
+ } else if (!strcmp(name, "cell_channels")) {
+ curr_conn->cell_channels = (bool)*(int *)val;
+ } else if (!strcmp(name, "cell_servers")) {
+ curr_conn->cell_servers = (bool)*(int *)val;
+ } else if (!strcmp(name, "all_clients")) {
+ curr_conn->all_clients = (bool)*(int *)val;
+ } else if (!strcmp(name, "all_channels")) {
+ curr_conn->all_channels = (bool)*(int *)val;
+ } else if (!strcmp(name, "all_servers")) {
+ curr_conn->all_servers = (bool)*(int *)val;
+ } else if (!strcmp(name, "all_routers")) {
+ curr_conn->all_routers = (bool)*(int *)val;
+ } else if (!strcmp(name, "all_server_ops")) {
+ curr_conn->all_server_ops = (bool)*(int *)val;
+ } else if (!strcmp(name, "all_router_ops")) {
+ curr_conn->all_router_ops = (bool)*(int *)val;
+ } else if (!strcmp(name, "motd")) {
+ curr_conn->motd = (bool)*(int *)val;
+ } else if (!strcmp(name, "up_color")) {
+ curr_conn->up_color = strdup((char *)val);
+ } else if (!strcmp(name, "down_color")) {
+ curr_conn->down_color = strdup((char *)val);
+ } else if (!strcmp(name, "up_text_color")) {
+ curr_conn->up_text_color = strdup((char *)val);
+ } else if (!strcmp(name, "down_text_color")) {
+ curr_conn->down_text_color = strdup((char *)val);
+ } else {
+ retval = SILC_CONFIG_ESILENT;
+ }
+
+ return retval;
+}
+
+/* Command: loadmap, loadmaps the bitmap map image. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_loadmap)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!filename)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("loadmap: file: %s", filename));
+
+ /* Destroy old bitmap if loadmaped */
+ silc_free(map->bitmap);
+
+ /* Loadmap the bitmap image */
+ if (!silc_map_load_ppm(map, filename))
+ retval = SILC_CONFIG_ESILENT;
+
+ /* Cleanup */
+ silc_free(filename);
+ filename = NULL;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "filename"))
+ filename = strdup((char *)val);
+ else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: writemap, writemap the map into bitmap file. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_writemap)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!filename)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("writemap: file: %s", filename));
+
+ /* Execute directly if there are no connections */
+ if (map->conns_num == 0) {
+ /* Writemap the map */
+ if (!silc_map_write_ppm(map, filename))
+ retval = SILC_CONFIG_ESILENT;
+ } else {
+ map->writemap.filename = strdup(filename);
+ map->writemap.writemap = TRUE;
+ }
+
+ /* Cleanup */
+ silc_free(filename);
+ filename = NULL;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "filename"))
+ filename = strdup((char *)val);
+ else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: writemaphtml, writes HTML map of the image map. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_writemaphtml)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!filename)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("writehmaphtml: file: %s", filename));
+
+ /* Will generate HTML map page */
+ map->writemaphtml.filename = filename;
+ map->writemaphtml.text = text;
+ if (lon)
+ map->writemaphtml.x = silc_map_lon2x(map, lon);
+ if (lat)
+ map->writemaphtml.y = silc_map_lat2y(map, lat);
+ map->writemaphtml.writemaphtml = TRUE;
+
+ /* Clean up */
+ silc_free(lat);
+ silc_free(lon);
+ filename = NULL;
+ text = NULL;
+ lat = lon = NULL;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "filename"))
+ filename = strdup((char *)val);
+ else if (!strcmp(name, "image"))
+ text = strdup((char *)val);
+ else if (!strcmp(name, "cut_lat"))
+ lat = strdup((char *)val);
+ else if (!strcmp(name, "cut_lon"))
+ lon = strdup((char *)val);
+ else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: writehtml, writes the gathered data into HTML pages. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_writehtml)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!filename)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("writehtml: file: %s", filename));
+
+ /* Will generate HTML pages */
+ map->writehtml.filename = filename;
+ map->writehtml.writehtml = TRUE;
+ filename = NULL;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "filename"))
+ filename = strdup((char *)val);
+ else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: cut, cut's a specified area from the map. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_cut)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+ bool ret;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ SilcMap map2;
+
+ if (!filename || !lat || !lon || !width || !height)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("cut: lat: %s lon: %s w: %ld h: %ld file: %s",
+ lat, lon, width, height, filename));
+
+ /* Execute directly if not inside connection block */
+ if (!curr_conn) {
+ if (!map->conns_num) {
+ /* Before any connection blocks */
+
+ /* Cut the chunk from the map. */
+ ret = silc_map_cut(map, silc_map_lon2x(map, lon),
+ silc_map_lat2y(map, lat),
+ width, height, &map2);
+ if (ret) {
+ /* Writemap the chunk. */
+ ret = silc_map_write_ppm(map2, filename);
+ silc_map_free(map2);
+ }
+ if (!ret)
+ retval = SILC_CONFIG_ESILENT;
+ } else {
+ /* After all connection blocks */
+ map->cut.filename = strdup(filename);
+ map->cut.x = silc_map_lon2x(map, lon);
+ map->cut.y = silc_map_lat2y(map, lat);
+ map->cut.width = width;
+ map->cut.height = height;
+ map->cut.cut = TRUE;
+ }
+ } else {
+ SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
+ if (!cmd)
+ return SILC_CONFIG_ESILENT;
+
+ silc_dlist_add(curr_conn->commands, cmd);
+ cmd->filename = strdup(filename);
+ cmd->x = silc_map_lon2x(map, lon);
+ cmd->y = silc_map_lat2y(map, lat);
+ cmd->width = width;
+ cmd->height = height;
+ cmd->cut = TRUE;
+ }
+
+ /* Cleanup */
+ silc_free(filename);
+ silc_free(lat);
+ silc_free(lon);
+ filename = NULL;
+ lat = NULL;
+ lon = NULL;
+ width = 0;
+ height = 0;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "lat"))
+ lat = strdup((char *)val);
+ else if (!strcmp(name, "lon"))
+ lon = strdup((char *)val);
+ else if (!strcmp(name, "width"))
+ width = (SilcUInt32)*(int *)val;
+ else if (!strcmp(name, "height"))
+ height = (SilcUInt32)*(int *)val;
+ else if (!strcmp(name, "filename"))
+ filename = strdup((char *)val);
+ else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: rectangle, draws a rectangle on the map. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_rectangle)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+ bool ret;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!lat || !lon)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("rectangle: lat: %s lon: %s color: %d %d %d",
+ lat, lon, r, g, b));
+
+ if (lr == -1) {
+ lr = r;
+ lg = g;
+ lb = b;
+ }
+
+ /* Execute directly if not for connection */
+ if (!curr_conn) {
+ /* Draw the rectangle */
+ ret = silc_map_draw_rectangle(map, silc_map_lon2x(map, lon),
+ silc_map_lat2y(map, lat),
+ r, g, b, text, lposx, lposy, lr, lg, lb);
+ if (!ret)
+ retval = SILC_CONFIG_ESILENT;
+ } else {
+ SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
+ if (!cmd)
+ return SILC_CONFIG_ESILENT;
+
+ silc_dlist_add(curr_conn->commands, cmd);
+ cmd->r = r;
+ cmd->g = g;
+ cmd->b = b;
+ cmd->lr = lr;
+ cmd->lg = lg;
+ cmd->lb = lb;
+ cmd->x = silc_map_lon2x(map, lon);
+ cmd->y = silc_map_lat2y(map, lat);
+ cmd->text = strdup(text);
+ cmd->lposx = lposx;
+ cmd->lposy = lposy;
+ cmd->draw_rectangle = TRUE;
+ cmd->color_set = color_set;
+ cmd->lcolor_set = lcolor_set;
+ }
+
+ /* Cleanup */
+ silc_free(text);
+ silc_free(lat);
+ silc_free(lon);
+ text = NULL;
+ lat = NULL;
+ lon = NULL;
+ lposx = 0;
+ lposy = 0;
+ lr = lg = lb = -1;
+ color_set = lcolor_set = FALSE;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "lat"))
+ lat = strdup((char *)val);
+ else if (!strcmp(name, "lon"))
+ lon = strdup((char *)val);
+ else if (!strcmp(name, "color")) {
+ if (!silc_map_parse_color((const char *)val, &r, &g, &b))
+ retval = SILC_CONFIG_ESILENT;
+ color_set = TRUE;
+ } else if (!strcmp(name, "label"))
+ text = strdup((char *)val);
+ else if (!strcmp(name, "lposx"))
+ lposx = (SilcInt32)*(int *)val;
+ else if (!strcmp(name, "lposy"))
+ lposy = (SilcInt32)*(int *)val;
+ else if (!strcmp(name, "lcolor")) {
+ if (!silc_map_parse_color((const char *)val, &lr, &lg, &lb))
+ retval = SILC_CONFIG_ESILENT;
+ lcolor_set = TRUE;
+ } else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: circle, draws a circle on the map. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_circle)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+ bool ret;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!lat || !lon)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("circle: lat: %s lon: %s color: %d %d %d",
+ lat, lon, r, g, b));
+
+ if (lr == -1) {
+ lr = r;
+ lg = g;
+ lb = b;
+ }
+
+ /* Execute directly if not for connection */
+ if (!curr_conn) {
+ /* Draw the circle */
+ ret = silc_map_draw_circle(map, silc_map_lon2x(map, lon),
+ silc_map_lat2y(map, lat),
+ r, g, b, text, lposx, lposy, lr, lg, lb);
+ if (!ret)
+ retval = SILC_CONFIG_ESILENT;
+ } else {
+ SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
+ if (!cmd)
+ return SILC_CONFIG_ESILENT;
+
+ silc_dlist_add(curr_conn->commands, cmd);
+ cmd->r = r;
+ cmd->g = g;
+ cmd->b = b;
+ cmd->lr = lr;
+ cmd->lg = lg;
+ cmd->lb = lb;
+ cmd->x = silc_map_lon2x(map, lon);
+ cmd->y = silc_map_lat2y(map, lat);
+ cmd->text = strdup(text);
+ cmd->lposx = lposx;
+ cmd->lposy = lposy;
+ cmd->draw_circle = TRUE;
+ cmd->color_set = color_set;
+ cmd->lcolor_set = lcolor_set;
+ }
+
+ /* Cleanup */
+ silc_free(text);
+ silc_free(lat);
+ silc_free(lon);
+ text = NULL;
+ lat = NULL;
+ lon = NULL;
+ lposx = 0;
+ lposy = 0;
+ lr = lg = lb = -1;
+ color_set = lcolor_set = FALSE;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "lat"))
+ lat = strdup((char *)val);
+ else if (!strcmp(name, "lon"))
+ lon = strdup((char *)val);
+ else if (!strcmp(name, "color")) {
+ if (!silc_map_parse_color((const char *)val, &r, &g, &b))
+ retval = SILC_CONFIG_ESILENT;
+ color_set = TRUE;
+ } else if (!strcmp(name, "label"))
+ text = strdup((char *)val);
+ else if (!strcmp(name, "lposx"))
+ lposx = (SilcInt32)*(int *)val;
+ else if (!strcmp(name, "lposy"))
+ lposy = (SilcInt32)*(int *)val;
+ else if (!strcmp(name, "lcolor")) {
+ if (!silc_map_parse_color((const char *)val, &lr, &lg, &lb))
+ retval = SILC_CONFIG_ESILENT;
+ lcolor_set = TRUE;
+ } else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: line, draws a line between two points in the map. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_line)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+ bool ret;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!lat || !lon || !lat2 || !lon2)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("line: alat: %s alon: %s blat: %s blon: %s "
+ "width: %ld color: %d %d %d",
+ lat, lon, lat2, lon2, width, r, g, b));
+
+ if (!width)
+ width = 1;
+
+ /* Execute directly if not for connection */
+ if (!curr_conn) {
+ /* Draw the line */
+ ret = silc_map_draw_line(map, width,
+ silc_map_lon2x(map, lon),
+ silc_map_lat2y(map, lat),
+ silc_map_lon2x(map, lon2),
+ silc_map_lat2y(map, lat2),
+ r, g, b);
+ if (!ret)
+ retval = SILC_CONFIG_ESILENT;
+ } else {
+ SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
+ if (!cmd)
+ return SILC_CONFIG_ESILENT;
+
+ silc_dlist_add(curr_conn->commands, cmd);
+ cmd->r = r;
+ cmd->g = g;
+ cmd->b = b;
+ cmd->x = silc_map_lon2x(map, lon);
+ cmd->y = silc_map_lat2y(map, lat);
+ cmd->x2 = silc_map_lon2x(map, lon2);
+ cmd->y2 = silc_map_lat2y(map, lat2);
+ cmd->width = width;
+ cmd->draw_line = TRUE;
+ cmd->color_set = color_set;
+ }
+
+ /* Cleanup */
+ silc_free(lat);
+ silc_free(lon);
+ silc_free(lat2);
+ silc_free(lon2);
+ lat = NULL;
+ lon = NULL;
+ lat2 = NULL;
+ lon2 = NULL;
+ width = 0;
+ color_set = FALSE;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "a_lat"))
+ lat = strdup((char *)val);
+ else if (!strcmp(name, "a_lon"))
+ lon = strdup((char *)val);
+ else if (!strcmp(name, "b_lat"))
+ lat2 = strdup((char *)val);
+ else if (!strcmp(name, "b_lon"))
+ lon2 = strdup((char *)val);
+ else if (!strcmp(name, "width"))
+ width = (SilcUInt32)*(int *)val;
+ else if (!strcmp(name, "color")) {
+ if (!silc_map_parse_color((const char *)val, &r, &g, &b))
+ retval = SILC_CONFIG_ESILENT;
+ color_set = TRUE;
+ } else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Command: text, prints a text on the map. */
+
+SILC_CONFIG_CALLBACK(silc_map_cmd_text)
+{
+ SilcMap map = context;
+ int retval = SILC_CONFIG_OK;
+ bool ret;
+
+ if (type == SILC_CONFIG_ARG_BLOCK) {
+ if (!lat || !lon || !text)
+ return SILC_CONFIG_EMISSFIELDS;
+
+ SILC_LOG_DEBUG(("text: lat: %s lon: %s color: %d %d %d text: %s",
+ lat, lon, r, g, b, text));
+
+ /* Execute directly if not for connection */
+ if (!curr_conn) {
+ /* Print the text */
+ ret = silc_map_draw_text(map, text,
+ silc_map_lon2x(map, lon),
+ silc_map_lat2y(map, lat),
+ r, g, b);
+ if (!ret)
+ retval = SILC_CONFIG_ESILENT;
+ } else {
+ SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
+ if (!cmd)
+ return SILC_CONFIG_ESILENT;
+
+ silc_dlist_add(curr_conn->commands, cmd);
+ cmd->r = r;
+ cmd->g = g;
+ cmd->b = b;
+ cmd->x = silc_map_lon2x(map, lon);
+ cmd->y = silc_map_lat2y(map, lat);
+ cmd->text = strdup(text);
+ cmd->draw_text = TRUE;
+ cmd->color_set = color_set;
+ }
+
+ /* Cleanup */
+ silc_free(text);
+ silc_free(lat);
+ silc_free(lon);
+ text = NULL;
+ lat = NULL;
+ lon = NULL;
+ color_set = FALSE;
+
+ return retval;
+ }
+
+ if (!strcmp(name, "lat"))
+ lat = strdup((char *)val);
+ else if (!strcmp(name, "lon"))
+ lon = strdup((char *)val);
+ else if (!strcmp(name, "color")) {
+ if (!silc_map_parse_color((const char *)val, &r, &g, &b))
+ retval = SILC_CONFIG_ESILENT;
+ color_set = TRUE;
+ } else if (!strcmp(name, "text"))
+ text = strdup((char *)val);
+ else
+ retval = SILC_CONFIG_ESILENT;
+
+ return retval;
+}
+
+/* Parses the commands from the file `filename'. */
+
+bool silc_map_commands_parse(SilcMap map, const char *filename)
+{
+ SilcConfigEntity ent;
+ SilcConfigFile *file;
+ bool retval = TRUE;
+ int ret;
+
+ SILC_LOG_DEBUG(("Parsing commands"));
+
+ /* Open commands file */
+ file = silc_config_open(filename);
+ if (!file) {
+ fprintf(stderr, "Cannot open commands file '%s'\n", filename);
+ return FALSE;
+ }
+
+ /* Parse the commands */
+ ent = silc_config_init(file);
+ silc_config_register_table(ent, silc_map_table_main, map);
+ ret = silc_config_main(ent);
+
+ SILC_LOG_DEBUG(("Parsing status: %s", silc_config_strerror(ret)));
+
+ if (ret && ret != SILC_CONFIG_ESILENT) {
+ fprintf(stderr, "Error parsing commands: %s, line %ld\n",
+ silc_config_strerror(ret), silc_config_get_line(file));
+ retval = FALSE;
+ }
+
+ /* Cleanup */
+ silc_config_close(file);
+ return retval;
+}
--- /dev/null
+/*
+
+ silcmap_html.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2003 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcmap.h"
+
+/* Write the HTML data file of the gathered data from the connection. */
+
+bool silc_map_writehtml(SilcMap map, SilcMapConnection mapconn)
+{
+ FILE *fp;
+ char *hostname;
+ char filename[256];
+
+ /* Generate data filename. First configure hostname is the filename */
+ silc_dlist_start(mapconn->hostnames);
+ hostname = silc_dlist_get(mapconn->hostnames);
+ memset(filename, 0, sizeof(filename));
+ snprintf(filename, sizeof(filename) - 1, "%s_%d.html", hostname,
+ mapconn->port);
+
+ /* Open for writing */
+ fp = fopen(filename, "w+");
+ if (!fp) {
+ fprintf(stderr, "Could not open file '%s'\n", filename);
+ return FALSE;
+ }
+
+ /* Write the HTML page */
+
+ fprintf(fp, "<!-- Automatically generated by silcmap --!>\n");
+ fprintf(fp, "<br /><hr ><br />\n");
+
+ /* General stuff */
+
+ fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n");
+ silc_dlist_start(mapconn->hostnames);
+ while ((hostname = silc_dlist_get(mapconn->hostnames)) != SILC_LIST_END)
+ fprintf(fp, "<tr><td><b>Hostname</b></td><td> :</td><td> %s</td></tr>\n", hostname);
+
+ silc_dlist_start(mapconn->ips);
+ while ((hostname = silc_dlist_get(mapconn->ips)) != SILC_LIST_END)
+ fprintf(fp, "<tr><td><b>IP</b></td><td> :</td><td> %s</td></tr>\n", hostname);
+
+ fprintf(fp, "<tr><td><b>Port</b></td><td> :</td><td> %d</td></tr>\n", mapconn->port);
+ fprintf(fp, "<tr><td><b>Country</b></td><td> :</td><td> %s</td></tr>\n", mapconn->country);
+ fprintf(fp, "<tr><td><b>City</b></td><td> :</td><td> %s</td></tr>\n", mapconn->city);
+ fprintf(fp, "<tr><td><b>Admin</b></td><td> :</td><td> %s</td></tr>\n", mapconn->admin);
+ fprintf(fp, "</table>\n");
+
+ /* Public key */
+ if (mapconn->public_key) {
+ SilcPublicKey public_key;
+ SilcPublicKeyIdentifier ident;
+ char *fingerprint, *babbleprint;
+ unsigned char *pk;
+ SilcUInt32 pk_len;
+ SilcPKCS pkcs;
+ SilcUInt32 key_len = 0;
+ FILE *pd;
+ unsigned char *pdd;
+
+ fprintf(fp, " <br /><hr ><br />\n");
+ fprintf(fp, "<b>Public Key:</b> <br />\n");
+ fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n");
+
+ if (silc_pkcs_load_public_key(mapconn->public_key, &public_key,
+ SILC_PKCS_FILE_PEM) == FALSE)
+ if (silc_pkcs_load_public_key(mapconn->public_key, &public_key,
+ SILC_PKCS_FILE_BIN) == FALSE) {
+ fprintf(stderr, "Could not load public key file `%s'\n",
+ mapconn->public_key);
+ return FALSE;
+ }
+
+ ident = silc_pkcs_decode_identifier(public_key->identifier);
+ pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+ babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+ if (silc_pkcs_alloc(public_key->name, &pkcs)) {
+ key_len = silc_pkcs_public_key_set(pkcs, public_key);
+ silc_pkcs_free(pkcs);
+ }
+
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Public key file</td><td> :</td><td> <a href=\"%s\">%s</a></td></tr>\n",
+ mapconn->public_key, mapconn->public_key);
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Algorithm</td><td> :</td><td> %s</td></tr>\n", public_key->name);
+ if (key_len) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Key length (bits)</td><td> :</td><td> %d</td></tr>\n", (unsigned int)key_len);
+ }
+ if (ident->realname) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Real name</td><td> :</td><td> %s</td></tr>\n", ident->realname);
+ }
+ if (ident->username) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Username</td><td> :</td><td> %s</td></tr>\n", ident->username);
+ }
+ if (ident->host) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Hostname</td><td> :</td><td> %s</td></tr>\n", ident->host);
+ }
+ if (ident->email) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Email</td><td> :</td><td> %s</td></tr>\n", ident->email);
+ }
+ if (ident->org) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Organization</td><td> :</td><td> %s</td></tr>\n", ident->org);
+ }
+ if (ident->country) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Country</td><td> :</td><td> %s</td></tr>\n", ident->country);
+ }
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Fingerprint (SHA1)</td><td> :</td><td> %s</td></tr>\n", fingerprint);
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Babbleprint (SHA1)</td><td> :</td><td> %s</td></tr>\n", babbleprint);
+ fprintf(fp, "</table>\n");
+
+ pd = fopen(mapconn->public_key, "r");
+ if (!pd)
+ return FALSE;
+
+ pk_len = silc_file_size(mapconn->public_key);
+ pdd = silc_calloc(pk_len + 1, sizeof(*pdd));
+ if (!pdd)
+ return FALSE;
+ fread(pdd, pk_len, 1, pd);
+
+ fprintf(fp, "<pre><tt>\n");
+ fprintf(fp, "%s", pdd);
+ fprintf(fp, "</tt></pre>\n");
+
+ fclose(pd);
+ silc_free(pdd);
+ silc_free(fingerprint);
+ silc_free(babbleprint);
+ silc_free(pk);
+ silc_pkcs_public_key_free(public_key);
+ silc_pkcs_free_identifier(ident);
+ }
+
+ /* Description */
+ if (mapconn->description && mapconn->description[0]) {
+ fprintf(fp, "<hr ><br />\n");
+ fprintf(fp, "<b>Description:</b> <br />\n");
+ fprintf(fp, "%s<br /> <br />\n", mapconn->description);
+ }
+
+ /* Status */
+ if (mapconn->connect) {
+ fprintf(fp, "<hr ><br />\n");
+ fprintf(fp, "<b>Server status:</b> <br />\n");
+ if (mapconn->down)
+ fprintf(fp,
+ "Server is currently down and unreachable. "
+ "Please try again later to connect the server.<br />\n");
+ else
+ fprintf(fp,
+ "Server is up and running<br />\n");
+ }
+
+ if (mapconn->connect && !mapconn->down) {
+ int days, hours, mins, secs, uptime;
+
+ uptime = mapconn->data.uptime;
+ days = uptime / (24 * 60 * 60);
+ uptime -= days * (24 * 60 * 60);
+ hours = uptime / (60 * 60);
+ uptime -= hours * (60 * 60);
+ mins = uptime / 60;
+ uptime -= mins * 60;
+ secs = uptime;
+
+ /* Statistics */
+ fprintf(fp, "<br />\n");
+ fprintf(fp, "<b>Server statistics:</b> <br />\n");
+ fprintf(fp, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n");
+ if (mapconn->starttime) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Server start time</td><td> :</td><td> %s<td></tr>\n",
+ silc_get_time(mapconn->data.starttime));
+ }
+ if (mapconn->uptime) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Server uptime</td><td> :</td><td> %d days %d hours %d mins %d secs<td></tr>\n",
+ days, hours, mins, secs);
+ }
+ if (mapconn->clients) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Local clients</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.clients);
+ }
+ if (mapconn->channels) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Local channels</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.channels);
+ }
+ if (mapconn->server_ops) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Local server operators</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.server_ops);
+ }
+ if (mapconn->router_ops) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Local router operators</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.router_ops);
+ }
+ if (mapconn->cell_clients) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Cell clients</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.cell_clients);
+ }
+ if (mapconn->cell_channels) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Cell channels</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.cell_channels);
+ }
+ if (mapconn->cell_servers) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "Cell servers</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.cell_servers);
+ }
+ if (mapconn->all_clients) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "All SILC clients</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.all_clients);
+ }
+ if (mapconn->all_channels) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "All SILC channels</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.all_channels);
+ }
+ if (mapconn->all_servers) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "All SILC servers</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.all_servers);
+ }
+ if (mapconn->all_routers) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "All SILC routers</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.all_routers);
+ }
+ if (mapconn->all_server_ops) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "All SILC server operators</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.all_server_ops);
+ }
+ if (mapconn->all_router_ops) {
+ fprintf(fp, "<tr><td> ");
+ fprintf(fp, "All SILC router operators</td><td> :</td><td> %ld</td></tr>\n",
+ mapconn->data.all_router_ops);
+ }
+ fprintf(fp, "</table>\n");
+ }
+
+ /* motd */
+ if (mapconn->motd) {
+ fprintf(fp, " <br /><hr ><br />\n");
+ fprintf(fp, "<b>Message of the Day:</b> <br />\n");
+ fprintf(fp, "<pre><tt>%s</tt><pre>\n", mapconn->data.motd);
+ }
+
+ fprintf(fp, "<br />\n");
+
+ fclose(fp);
+ return TRUE;
+}
+
+/* Write the HTML index file that lists all servers. */
+
+bool silc_map_writehtml_index(SilcMap map)
+{
+ SilcMapConnection mapconn;
+ char *hostname, *ip;
+ FILE *fp;
+
+ /* Open for writing */
+ fp = fopen(map->writehtml.filename, "w+");
+ if (!fp) {
+ fprintf(stderr, "Could not open file '%s'\n", map->writehtml.filename);
+ return FALSE;
+ }
+
+ /* Produce a simple HTML index file of all servers */
+
+ fprintf(fp, "<!-- Automatically generated by silcmap --!>\n");
+ fprintf(fp, "<br />\n");
+ fprintf(fp, "<table cellspacing=\"2\" cellpadding=\"2\" border=\"1\">\n");
+ fprintf(fp,
+ "<tr>\n"
+ "<td align=\"center\"><b>Hostname</b></td>\n"
+ "<td align=\"center\"><b>IPv4 Address</b></td>\n"
+ "<td align=\"center\"><b>Port</b></td>\n"
+ "<td align=\"center\"><b>Country</b></td>\n"
+ "<td align=\"center\"><b>Oper</b></td>\n"
+ "</tr>\n");
+
+ silc_dlist_start(map->conns);
+ while ((mapconn = silc_dlist_get(map->conns)) != SILC_LIST_END) {
+
+ silc_dlist_start(mapconn->hostnames);
+ hostname = silc_dlist_get(mapconn->hostnames);
+ silc_dlist_start(mapconn->ips);
+ ip = silc_dlist_get(mapconn->ips);
+
+ fprintf(fp,
+ "<tr>\n"
+ "<td align = \"center\"> <a href=\"%s_%d.html\">%s</a></td>\n"
+ "<td align = \"center\"> %s</td>\n"
+ "<td align = \"center\"> %d</td>\n"
+ "<td align = \"center\"> %s</td>\n"
+ "<td align = \"center\"> %s</td>\n"
+ "</tr>\n", hostname, mapconn->port,
+ hostname, ip, mapconn->port, mapconn->country, mapconn->admin);
+ }
+
+ fprintf(fp, "</table><br />\n");
+
+ return TRUE;
+}
+
+/* Creates a HTML map file, which can be used to allow user to click
+ URLs on the image at the specified locations. */
+
+bool silc_map_writemaphtml(SilcMap map)
+{
+ SilcMapConnection mapconn;
+ SilcMapCommand cmd;
+ char *hostname, url[256];
+ FILE *fp;
+ int xx , yy, w, h;
+
+ /* Open for writing */
+ fp = fopen(map->writemaphtml.filename, "w+");
+ if (!fp) {
+ fprintf(stderr, "Could not open file '%s'\n", map->writemaphtml.filename);
+ return FALSE;
+ }
+
+ /* The target may be portion of the original map, so we must make the
+ new coordinates relative to the new map. */
+ xx = map->writemaphtml.x;
+ yy = map->writemaphtml.y;
+
+ memset(url, 0, sizeof(url));
+
+ fprintf(fp, "<!-- Automatically generated by silcmap --!>\n");
+ fprintf(fp, "<br />\n");
+ fprintf(fp, "<img src=\"%s\" usemap=\"#map\" border=\"0\">\n",
+ map->writemaphtml.text);
+ fprintf(fp, "<map name=\"map\">\n");
+
+ memset(url, 0, sizeof(url));
+
+ silc_dlist_start(map->conns);
+ while ((mapconn = silc_dlist_get(map->conns)) != SILC_LIST_END) {
+ if (mapconn->writemaphtml_url && mapconn->writemaphtml_url[0]) {
+ silc_strncat(url, sizeof(url), mapconn->writemaphtml_url,
+ strlen(mapconn->writemaphtml_url));
+ } else {
+ silc_dlist_start(mapconn->hostnames);
+ hostname = silc_dlist_get(mapconn->hostnames);
+ snprintf(url, sizeof(url) - 1, "%s_%d.html", hostname, mapconn->port);
+ }
+
+ /* Print the positions of various items on the map into the map file */
+ silc_dlist_start(mapconn->commands);
+ while ((cmd = silc_dlist_get(mapconn->commands)) != SILC_LIST_END) {
+ if (cmd->draw_text) {
+ w = strlen(cmd->text) * 5;
+ h = map->font.height - 2;
+ fprintf(fp,
+ "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
+ (int)(cmd->x - xx), (int)(cmd->y - yy), w, h, url);
+ }
+
+ if (cmd->draw_circle) {
+ w = 4;
+ fprintf(fp,
+ "<area shape=\"circle\" coords=\"%d,%d,%d\" href=\"%s\">\n",
+ (int)(cmd->x - xx), (int)(cmd->y - yy), w, url);
+ if (cmd->text) {
+ w = strlen(cmd->text) * 5;
+ h = map->font.height - 2;
+ fprintf(fp,
+ "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
+ (int)(cmd->x - xx + cmd->lposx),
+ (int)(cmd->y - yy - cmd->lposy),
+ (int)(cmd->x - xx + cmd->lposx + w),
+ (int)(cmd->y - yy - cmd->lposy + h), url);
+ }
+ }
+
+ if (cmd->draw_rectangle) {
+ w = 7;
+ h = 6;
+ fprintf(fp,
+ "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
+ (int)(cmd->x - xx), (int)(cmd->y - yy),
+ (int)(cmd->x - xx + w), (int)(cmd->y - yy + h), url);
+ if (cmd->text) {
+ w = strlen(cmd->text) * 5;
+ h = map->font.height - 2;
+ fprintf(fp,
+ "<area shape=\"rect\" coords=\"%d,%d,%d,%d\" href=\"%s\">\n",
+ (int)(cmd->x - xx + cmd->lposx),
+ (int)(cmd->y - yy - cmd->lposy),
+ (int)(cmd->x - xx + cmd->lposx + w),
+ (int)(cmd->y - yy - cmd->lposy + h), url);
+ }
+ }
+ }
+ }
+
+ fprintf(fp, "</map><br />\n");
+ fclose(fp);
+
+ return TRUE;
+}
lib/silcsftp/tests/Makefile
doc/example_silcd.conf
includes/silcincludes.h
+silcmap/Makefile
)
if test "x$silc_dist" = "xsilc-client" ||