[Freeciv-Dev] Re: (PR#2757) Patch: New metaserver sample civclient/civse
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=2757 >
new version. server only. not broken. works!
go to meta.freeciv.org/~kauf/metaserver.phtml to see your handiwork.
-mike
? freeciv.spec
? server/.meta.c.swp
Index: server/connecthand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/connecthand.c,v
retrieving revision 1.30
diff -u -r1.30 connecthand.c
--- server/connecthand.c 15 Sep 2004 04:48:27 -0000 1.30
+++ server/connecthand.c 19 Sep 2004 05:14:48 -0000
@@ -175,7 +175,7 @@
send_conn_info(dest, &game.est_connections);
conn_list_insert_back(&game.est_connections, pconn);
send_conn_info(&game.est_connections, dest);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
}
/**************************************************************************
Index: server/meta.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/meta.c,v
retrieving revision 1.60
diff -u -r1.60 meta.c
--- server/meta.c 17 May 2004 02:16:15 -0000 1.60
+++ server/meta.c 19 Sep 2004 05:14:48 -0000
@@ -11,28 +11,11 @@
GNU General Public License for more details.
***********************************************************************/
-/*
- * This bit sends "I'm here" packages to the metaserver.
- */
-
-/*
-The desc block should look like this:
-1) GameName - Freeciv
-2) Version - 1.5.0
-3) State - Running(Open for new players)
-4) Host - Empty
-5) Port - 5555
-6) NoPlayers - 3
-7) InfoText - Warfare - starts at 8:00 EMT
-
-The info string should look like this:
- GameSpecific text block
-*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -57,9 +40,12 @@
#include <winsock.h>
#endif
+#include "capstr.h"
+#include "connection.h"
#include "dataio.h"
#include "fcintl.h"
#include "log.h"
+#include "mem.h"
#include "netintf.h"
#include "support.h"
#include "timing.h"
@@ -72,9 +58,10 @@
bool server_is_open = FALSE;
-static int sockfd=0;
static union my_sockaddr meta_addr;
-
+static char metaname[MAX_LEN_ADDR];
+static int metaport;
+static char *metaserver_path;
/*************************************************************************
Return static string with default info line to send to metaserver.
@@ -99,11 +86,6 @@
*************************************************************************/
void meta_addr_split(void)
{
- char *metaserver_port_separator = strchr(srvarg.metaserver_addr, ':');
-
- if (metaserver_port_separator) {
- sscanf(metaserver_port_separator + 1, "%hu", &srvarg.metaserver_port);
- }
}
/*************************************************************************
@@ -111,122 +93,234 @@
*************************************************************************/
char *meta_addr_port(void)
{
- static char retstr[300];
+ return srvarg.metaserver_addr;
+}
- if (srvarg.metaserver_port == DEFAULT_META_SERVER_PORT) {
- sz_strlcpy(retstr, srvarg.metaserver_addr);
- } else {
- my_snprintf(retstr, sizeof(retstr),
- "%s:%d", srvarg.metaserver_addr, srvarg.metaserver_port);
- }
+/*************************************************************************
+...
+*************************************************************************/
+static void metaserver_failed(void)
+{
+ con_puts(C_METAERROR, _("Not reporting to the metaserver in this game."));
+ con_flush();
- return retstr;
+ server_close_meta();
}
/*************************************************************************
...
- Returns true if able to send
*************************************************************************/
-static bool send_to_metaserver(char *desc, char *info)
+static bool send_to_metaserver(int flags)
{
- unsigned char buffer[MAX_LEN_PACKET];
- struct data_out dout;
- size_t size;
+ static char msg[8192];
+ static char str[8192];
+ int rest = sizeof(str);
+ int n;
+ char *s = str;
+ const char *host = "somehost.somewhere.net";
+ char state;
+ int sock;
+// fz_FILE *f;
- dio_output_init(&dout, buffer, sizeof(buffer));
+ if (!server_is_open) {
+ return FALSE;
+ }
- if(sockfd<=0)
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ freelog(LOG_ERROR, "Metaserver: can't open stream socket: %s",
+ mystrerror());
+ metaserver_failed();
return FALSE;
+ }
- dio_put_uint16(&dout, 0);
- dio_put_uint8(&dout, PACKET_UDP_PCKT);
- dio_put_string(&dout, desc);
- dio_put_string(&dout, info);
+ if (connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) {
+ freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror());
+ metaserver_failed();
+ my_closesocket(sock);
+ return FALSE;
+ }
- size = dio_output_used(&dout);
+ switch(server_state) {
+ case PRE_GAME_STATE:
+ state = 'P';
+ break;
+ case SELECT_RACES_STATE:
+ state = 'S';
+ break;
+ case RUN_GAME_STATE:
+ state = 'R';
+ break;
+ case GAME_OVER_STATE:
+ state = 'E';
+ break;
+ default:
+ state = 'U';
+ break;
+ }
- dio_output_rewind(&dout);
- dio_put_uint16(&dout, size);
+ my_snprintf(s, rest,
+ "host=%s&port=%d&state=%c&",
+ host, srvarg.port, state);
+ s = end_of_strn(s, &rest);
+
+ if (flags & META_GOODBYE) {
+ mystrlcpy(s, "bye=1&", rest);
+ s = end_of_strn(s, &rest);
+ } else {
+ if (flags & META_VERSION) {
+ my_snprintf(s, rest,
+ "version=%s&",
+ my_url_encode(VERSION_STRING));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "patches=%s&",
+ my_url_encode("none"));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "capability=%s&",
+ my_url_encode(our_capability));
+ s = end_of_strn(s, &rest);
+ }
- my_writesocket(sockfd, buffer, size);
- return TRUE;
-}
+ if (flags & META_COMMENT) {
+ my_snprintf(s, rest,
+ "topic=%s&",
+ my_url_encode(srvarg.extra_metaserver_info));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "message=%s&",
+ my_url_encode(srvarg.metaserver_info_line));
+ s = end_of_strn(s, &rest);
+ }
-/*************************************************************************
-...
-*************************************************************************/
-void server_close_udp(void)
-{
- server_is_open = FALSE;
+ /* NOTE: send info for ALL players or none at all. */
+ if (get_num_human_and_ai_players() == 0) {
+ mystrlcpy(s, "dropplrs=1&", rest);
+ s = end_of_strn(s, &rest);
+ } else {
+ players_iterate(plr) {
+ char type;
+ struct connection *pconn = find_conn_by_user(plr->username);
+
+ if (is_barbarian(plr)) {
+ type = 'B';
+ } else if (plr->ai.control) {
+ type = 'A';
+ } else {
+ type = 'H';
+ }
+
+ my_snprintf(s, rest,
+ "plu[]=%s&",
+ my_url_encode(plr->username));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "plt[]=%c&",
+ type);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "pll[]=%s&",
+ my_url_encode(plr->name));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "pln[]=%s&",
+ my_url_encode(plr->nation != NO_NATION_SELECTED
+ ? get_nation_name_plural(plr->nation) : "none"));
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest,
+ "plh[]=%s&",
+ pconn ? my_url_encode(pconn->addr) : my_url_encode("none"));
+ s = end_of_strn(s, &rest);
+ } players_iterate_end;
+ }
- if(sockfd<=0)
- return;
- my_closesocket(sockfd);
- sockfd=0;
+ /* send some variables: should be listed in inverted order
+ * FIXME: these should be input from the settings array */
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("timeout"), game.timeout);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("endyear"), game.end_year);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("generator"), map.generator);
+ s = end_of_strn(s, &rest);
+
+ my_snprintf(s, rest, "vn[]=%s&vv[]=%d&",
+ my_url_encode("size"), map.size);
+ s = end_of_strn(s, &rest);
+ }
+
+ n = my_snprintf(msg, sizeof(msg),
+ "POST %s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n"
+ "%s\r\n",
+ metaserver_path,
+ metaname,
+ metaport,
+ sizeof(str)-rest+1,
+ str
+ );
+
+// printf("---------\n%s\n---\n", msg);
+
+// printf("---\n");
+
+ my_writesocket(sock, msg, n);
+
+// f = my_querysocket(sock, msg, n);
+// while (fz_fgets(msg, sizeof(msg), f))
+// fputs(msg, stdout);
+
+// printf("---\n");
+// fz_fclose(f);
+
+ return TRUE;
}
/*************************************************************************
...
*************************************************************************/
-static void metaserver_failed(void)
+void server_close_meta(void)
{
- con_puts(C_METAERROR, _("Not reporting to the metaserver in this game."));
- con_flush();
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_GOODBYE);
+
+ server_is_open = FALSE;
}
/*************************************************************************
...
*************************************************************************/
-void server_open_udp(void)
+void server_open_meta(void)
{
- char *metaname = srvarg.metaserver_addr;
- int metaport;
- union my_sockaddr bind_addr;
-
- /*
- * Fill in the structure "meta_addr" with the address of the
- * server that we want to connect with, checks if server address
- * is valid, both decimal-dotted and name.
- */
- metaport = srvarg.metaserver_port;
- if (!net_lookup_service(metaname, metaport, &meta_addr)) {
- freelog(LOG_ERROR, _("Metaserver: bad address: [%s:%d]."),
- metaname,
- metaport);
- metaserver_failed();
- return;
+ const char *path;
+
+ if (metaserver_path) {
+ free(metaserver_path);
+ metaserver_path = NULL;
}
-
- /*
- * Open a UDP socket (an Internet datagram socket).
- */
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- freelog(LOG_ERROR, "Metaserver: can't open datagram socket: %s",
- mystrerror());
- metaserver_failed();
+
+ if (!(path = my_lookup_httpd(metaname, &metaport, srvarg.metaserver_addr))) {
return;
}
+
+ metaserver_path = mystrdup(path);
- /*
- * Bind any local address for us and
- * associate datagram socket with server.
- */
- if (!net_lookup_service(srvarg.bind_addr, 0, &bind_addr)) {
+ if (!net_lookup_service(metaname, metaport, &meta_addr)) {
freelog(LOG_ERROR, _("Metaserver: bad address: [%s:%d]."),
- srvarg.bind_addr, 0);
- metaserver_failed();
- }
-
- /* set source IP */
- if (bind(sockfd, &bind_addr.sockaddr, sizeof(bind_addr)) == -1) {
- freelog(LOG_ERROR, "Metaserver: bind failed: %s", mystrerror());
- metaserver_failed();
- return;
- }
-
- /* no, this is not weird, see man connect(2) --vasc */
- if (connect(sockfd, &meta_addr.sockaddr, sizeof(meta_addr))==-1) {
- freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror());
+ metaname, metaport);
metaserver_failed();
return;
}
@@ -234,15 +328,12 @@
server_is_open = TRUE;
}
-
/**************************************************************************
...
**************************************************************************/
-bool send_server_info_to_metaserver(bool do_send, bool reset_timer)
+bool send_server_info_to_metaserver(bool do_send, bool reset_timer, int flags)
{
static struct timer *time_since_last_send = NULL;
- char desc[4096], info[4096];
- int num_nonbarbarians = get_num_human_and_ai_players();
if (reset_timer && time_since_last_send)
{
@@ -261,59 +352,6 @@
time_since_last_send = new_timer(TIMER_USER, TIMER_ACTIVE);
}
- /* build description block */
- desc[0]='\0';
-
- cat_snprintf(desc, sizeof(desc), "Freeciv\n");
- cat_snprintf(desc, sizeof(desc), VERSION_STRING"\n");
- /* note: the following strings are not translated here;
- we mark them so they may be translated when received by a client */
- switch(server_state) {
- case PRE_GAME_STATE:
- cat_snprintf(desc, sizeof(desc), N_("Pregame"));
- break;
- case RUN_GAME_STATE:
- cat_snprintf(desc, sizeof(desc), N_("Running"));
- break;
- case GAME_OVER_STATE:
- cat_snprintf(desc, sizeof(desc), N_("Game over"));
- break;
- default:
- cat_snprintf(desc, sizeof(desc), N_("Waiting"));
- }
- cat_snprintf(desc, sizeof(desc), "\n");
- cat_snprintf(desc, sizeof(desc), "%s\n", "UNSET");
- cat_snprintf(desc, sizeof(desc), "%d\n", srvarg.port);
- cat_snprintf(desc, sizeof(desc), "%d\n", num_nonbarbarians);
- cat_snprintf(desc, sizeof(desc), "%s %s", srvarg.metaserver_info_line,
- srvarg.extra_metaserver_info);
-
- /* now build the info block */
- info[0]='\0';
- cat_snprintf(info, sizeof(info),
- "Players:%d Min players:%d Max players:%d\n",
- num_nonbarbarians, game.min_players, game.max_players);
- cat_snprintf(info, sizeof(info),
- "Timeout:%d Year: %s\n",
- game.timeout, textyear(game.year));
-
-
- cat_snprintf(info, sizeof(info),
- "NO: NAME: HOST:\n");
- cat_snprintf(info, sizeof(info),
- "----------------------------------------\n");
-
- players_iterate(pplayer) {
- if (!is_barbarian(pplayer)) {
- /* Fixme: how should metaserver handle multi-connects?
- * Uses player_addr_hack() for now.
- */
- cat_snprintf(info, sizeof(info), "%2d %-20s %s\n",
- pplayer->player_no, pplayer->name,
- player_addr_hack(pplayer));
- }
- } players_iterate_end;
-
clear_timer_start(time_since_last_send);
- return send_to_metaserver(desc, info);
+ return send_to_metaserver(flags);
}
Index: server/meta.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/meta.h,v
retrieving revision 1.24
diff -u -r1.24 meta.h
--- server/meta.h 7 Nov 2002 16:04:54 -0000 1.24
+++ server/meta.h 19 Sep 2004 05:14:48 -0000
@@ -15,26 +15,26 @@
#include "shared.h" /* bool type */
-/*
- * Definitions for UDP.
- */
-
#define DEFAULT_META_SERVER_NO_SEND TRUE
-#define DEFAULT_META_SERVER_PORT 12245
-#define DEFAULT_META_SERVER_ADDR "meta.freeciv.org"
+#define DEFAULT_META_SERVER_ADDR
"http://meta.freeciv.org/~kauf/metaserver.phtml"
#define METASERVER_UPDATE_INTERVAL (3*60)
-#define PACKET_UDP_PCKT 2
+enum metainfo_type {
+ META_INFO = 0,
+ META_VERSION = 1,
+ META_COMMENT = 2,
+ META_GOODBYE = 4
+};
const char *default_meta_server_info_string(void);
void meta_addr_split(void);
char *meta_addr_port(void);
-void server_close_udp(void);
-void server_open_udp(void);
+void server_close_meta(void);
+void server_open_meta(void);
-bool send_server_info_to_metaserver(bool do_send, bool reset_timer);
+bool send_server_info_to_metaserver(bool do_send, bool reset_timer, int flags);
extern bool server_is_open;
Index: server/sernet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sernet.c,v
retrieving revision 1.121
diff -u -r1.121 sernet.c
--- server/sernet.c 20 Jul 2004 17:05:26 -0000 1.121
+++ server/sernet.c 19 Sep 2004 05:14:48 -0000
@@ -233,7 +233,7 @@
}
#endif
- server_close_udp();
+ server_close_meta();
my_shutdown_network();
}
@@ -397,7 +397,7 @@
sz_strlcpy(srvarg.metaserver_info_line,
"restarting for lack of players");
freelog(LOG_NORMAL, srvarg.metaserver_info_line);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_COMMENT);
server_state = GAME_OVER_STATE;
force_end_of_sniff = TRUE;
@@ -414,7 +414,7 @@
"restarting in %d seconds for lack of players",
srvarg.quitidle);
freelog(LOG_NORMAL, srvarg.metaserver_info_line);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_COMMENT);
}
} else {
last_noplayers = 0;
@@ -459,7 +459,7 @@
/* Don't wait if timeout == -1 (i.e. on auto games) */
if (server_state != PRE_GAME_STATE && game.timeout == -1) {
- (void) send_server_info_to_metaserver(FALSE, FALSE);
+ (void) send_server_info_to_metaserver(FALSE, FALSE, META_INFO);
return 0;
}
@@ -497,7 +497,7 @@
con_prompt_off(); /* output doesn't generate a new prompt */
if(select(max_desc+1, &readfs, &writefs, &exceptfs, &tv)==0) { /* timeout
*/
- (void) send_server_info_to_metaserver(FALSE, FALSE);
+ (void) send_server_info_to_metaserver(FALSE, FALSE, META_INFO);
if(game.timeout != 0
&& (time(NULL)>game.turn_start + game.timeout)
&& (server_state == RUN_GAME_STATE)){
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.196
diff -u -r1.196 srv_main.c
--- server/srv_main.c 16 Sep 2004 09:53:11 -0000 1.196
+++ server/srv_main.c 19 Sep 2004 05:14:48 -0000
@@ -176,7 +176,6 @@
srvarg.metaserver_no_send = DEFAULT_META_SERVER_NO_SEND;
sz_strlcpy(srvarg.metaserver_info_line, default_meta_server_info_string());
sz_strlcpy(srvarg.metaserver_addr, DEFAULT_META_SERVER_ADDR);
- srvarg.metaserver_port = DEFAULT_META_SERVER_PORT;
srvarg.bind_addr = NULL;
srvarg.port = DEFAULT_SOCK_PORT;
@@ -1375,7 +1374,7 @@
game.nplayers++;
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
if (!((game.nplayers == old_nplayers+1)
&& strcmp(player_name, pplayer->name)==0)) {
@@ -1396,7 +1395,7 @@
announce_ai_player(pplayer);
set_ai_level_direct(pplayer, pplayer->ai.skill_level);
}
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
}
/*************************************************************************
@@ -1545,7 +1544,7 @@
end_phase();
end_turn();
freelog(LOG_DEBUG, "Sendinfotometaserver");
- (void) send_server_info_to_metaserver(FALSE, FALSE);
+ (void) send_server_info_to_metaserver(FALSE, FALSE, META_INFO);
conn_list_do_unbuffer(&game.game_connections);
@@ -1603,10 +1602,10 @@
if(!(srvarg.metaserver_no_send)) {
freelog(LOG_NORMAL, _("Sending info to metaserver [%s]"),
meta_addr_port());
- server_open_udp(); /* open socket for meta server */
+ server_open_meta(); /* open socket for meta server */
}
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE,
META_VERSION|META_COMMENT);
/* accept new players, wait for serverop to start..*/
server_state = PRE_GAME_STATE;
@@ -1663,7 +1662,7 @@
sniff_packets(); /* Accepting commands. */
}
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
if (game.is_new_game) {
load_rulesets();
@@ -1784,7 +1783,7 @@
/* start the game */
server_state = RUN_GAME_STATE;
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
if(game.is_new_game) {
/* Before the player map is allocated (and initiailized)! */
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.350
diff -u -r1.350 stdinhand.c
--- server/stdinhand.c 17 Sep 2004 03:37:10 -0000 1.350
+++ server/stdinhand.c 19 Sep 2004 05:14:51 -0000
@@ -496,8 +496,8 @@
**************************************************************************/
static void open_metaserver_connection(struct connection *caller)
{
- server_open_udp();
- if (send_server_info_to_metaserver(TRUE, FALSE)) {
+ server_open_meta();
+ if (send_server_info_to_metaserver(TRUE, FALSE, META_VERSION|META_COMMENT)) {
notify_player(NULL, _("Open metaserver connection to [%s]."),
meta_addr_port());
}
@@ -508,8 +508,8 @@
**************************************************************************/
static void close_metaserver_connection(struct connection *caller)
{
- if (send_server_info_to_metaserver(TRUE, TRUE)) {
- server_close_udp();
+ if (send_server_info_to_metaserver(TRUE, TRUE, META_INFO)) {
+ server_close_meta();
notify_player(NULL, _("Close metaserver connection to [%s]."),
meta_addr_port());
}
@@ -569,7 +569,7 @@
return TRUE;
}
sz_strlcpy(srvarg.metaserver_info_line, arg);
- if (!send_server_info_to_metaserver(TRUE, FALSE)) {
+ if (!send_server_info_to_metaserver(TRUE, FALSE, META_COMMENT)) {
cmd_reply(CMD_METAINFO, caller, C_METAERROR,
_("Not reporting to the metaserver."));
} else {
@@ -823,7 +823,7 @@
notify_player(NULL, _("Game: %s has been added as an AI-controlled player."),
arg);
- (void) send_server_info_to_metaserver(TRUE, FALSE);
+ (void) send_server_info_to_metaserver(TRUE, FALSE, META_INFO);
pplayer = find_player_by_name(arg);
if (!pplayer)
@@ -954,8 +954,7 @@
"experimental");
if (*srvarg.metaserver_addr != '\0' &&
- ((0 != strcmp(srvarg.metaserver_addr, DEFAULT_META_SERVER_ADDR)) ||
- (srvarg.metaserver_port != DEFAULT_META_SERVER_PORT))) {
+ ((0 != strcmp(srvarg.metaserver_addr, DEFAULT_META_SERVER_ADDR)))) {
fprintf(script_file, "metaserver %s\n", meta_addr_port());
}
Index: utility/netintf.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/netintf.c,v
retrieving revision 1.21
diff -u -r1.21 netintf.c
--- utility/netintf.c 17 May 2004 02:16:15 -0000 1.21
+++ utility/netintf.c 19 Sep 2004 05:14:51 -0000
@@ -22,6 +22,7 @@
#include <errno.h>
#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef HAVE_ARPA_INET_H
@@ -226,6 +227,102 @@
return fz_from_stream(fp);
}
+/*************************************************************************
+ Returns a valid httpd server and port, plus the path to the resource
+ at the url location.
+*************************************************************************/
+const char *my_lookup_httpd(char *server, int *port, const char *url)
+{
+ const char *purl, *str, *ppath, *pport;
+
+ if ((purl = getenv("http_proxy"))) {
+ if (strncmp(purl, "http://", strlen("http://")) != 0) {
+ return NULL;
+ }
+ str = purl;
+ } else {
+ if (strncmp(url, "http://", strlen("http://")) != 0) {
+ return NULL;
+ }
+ str = url;
+ }
+
+ str += strlen("http://");
+
+ pport = strchr(str, ':');
+ ppath = strchr(str, '/');
+
+ /* snarf server. */
+ server[0] = '\0';
+
+ if (pport) {
+ strncat(server, str, MIN(MAX_LEN_ADDR, pport-str));
+ } else {
+ if (ppath) {
+ strncat(server, str, MIN(MAX_LEN_ADDR, ppath-str));
+ } else {
+ strncat(server, str, MAX_LEN_ADDR);
+ }
+ }
+
+ /* snarf port. */
+ if (!pport || sscanf(pport+1, "%d", port) != 1) {
+ *port = 80;
+ }
+
+ /* snarf path. */
+ if (!ppath) {
+ ppath = "/";
+ }
+
+ return (purl ? url : ppath);
+}
+
+/*************************************************************************
+ Returns TRUE if ch is an unreserved ASCII character.
+*************************************************************************/
+static bool is_url_safe(char ch)
+{
+ const char *unreserved = "-_.!~*'|";
+
+ if ((ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9')) {
+ return TRUE;
+ } else {
+ return (strchr(unreserved, ch) != NULL);
+ }
+}
+
+/***************************************************************
+ URL-encode a string as per RFC 2396.
+ Should work for all ASCII based charsets: including UTF-8.
+***************************************************************/
+const char *my_url_encode(const char *txt)
+{
+ static char buf[2048];
+ int pos;
+
+ /* in a worst case scenario every character needs "% HEX HEX" encoding. */
+ if (sizeof(buf) <= (3*strlen(txt))) {
+ return "";
+ }
+
+ for (pos = 0; *txt != '\0'; txt++) {
+
+ if (is_url_safe(*txt)) {
+ buf[pos] = *txt;
+ pos++;
+ } else if (*txt == ' ') {
+ buf[pos] = '+';
+ pos++;
+ } else {
+ pos += sprintf(&buf[pos], "%%%2x", *txt);
+ }
+ }
+ buf[pos] = '\0';
+
+ return buf;
+}
+
/**************************************************************************
Finds the next (lowest) free port.
**************************************************************************/
Index: utility/netintf.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/netintf.h,v
retrieving revision 1.11
diff -u -r1.11 netintf.h
--- utility/netintf.h 8 May 2004 19:21:01 -0000 1.11
+++ utility/netintf.h 19 Sep 2004 05:14:51 -0000
@@ -66,4 +66,7 @@
fz_FILE *my_querysocket(int sock, void *buf, size_t size);
int find_next_free_port(int starting_port);
+const char *my_lookup_httpd(char *server, int *port, const char *url);
+const char *my_url_encode(const char *txt);
+
#endif /* FC__NETINTF_H */
|
|