Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2004:
[Freeciv-Dev] Re: (PR#2757) Patch: New metaserver sample civclient/civse
Home

[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]
To: _vasc@xxxxxxxxxxx.pt_
Subject: [Freeciv-Dev] Re: (PR#2757) Patch: New metaserver sample civclient/civserver implementation
From: "Mike Kaufman" <kaufman@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 17 Sep 2004 15:50:42 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=2757 >

update for server only. probably broken.

-mike

? cvs
? 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        17 Sep 2004 22:49:10 -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       17 Sep 2004 22:49:10 -0000
@@ -33,6 +33,7 @@
 #include <config.h>
 #endif
 
+#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -57,9 +58,11 @@
 #include <winsock.h>
 #endif
 
+#include "capstr.h"
 #include "dataio.h"
 #include "fcintl.h"
 #include "log.h"
+#include "mem.h"
 #include "netintf.h"
 #include "support.h"
 #include "timing.h"
@@ -72,9 +75,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 +103,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,44 +110,204 @@
 *************************************************************************/
 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_udp();
 }
 
 /*************************************************************************
 ...
-  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;
+  char state;
 
-  dio_output_init(&dout, buffer, sizeof(buffer));
+  int sock;
+  fz_FILE *f;
 
-  if(sockfd<=0)
+  if (!server_is_open) {
     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 ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+    freelog(LOG_ERROR, "Metaserver: can't open stream socket: %s",
+           mystrerror());
+    metaserver_failed();
+    return FALSE;
+  }
+
+  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;
+  }
+
+  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;
+  }
+
+  my_snprintf(s, rest,
+    "host=&port=%d&state=%c&",
+    srvarg.port, state);
+  s = end_of_strn(s, &rest);
+
+  if (flags & META_GOODBYE) {
+    mystrlcpy(s, "goodbye=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,
+        "capability=%s&",
+        my_url_encode(our_capability));
+      s = end_of_strn(s, &rest);
+    }
+
+    if (flags & META_COMMENT) {
+      my_snprintf(s, rest,
+        "comment=%s+",
+        my_url_encode(srvarg.metaserver_info_line));
+      s = end_of_strn(s, &rest);
+
+      my_snprintf(s, rest,
+        "%s&",
+        my_url_encode(srvarg.extra_metaserver_info));
+      s = end_of_strn(s, &rest);
+    }
+
+    if (server_state < RUN_GAME_STATE) {
+      my_snprintf(s, rest,
+        "xsize=%d&"
+        "ysize=%d&"
+        "huts=%d&"
+        "generator=%d&"
+        "minplayers=%d&"
+        "maxplayers=%d&",
+        map.xsize,
+        map.ysize,
+        map.huts,
+        map.generator,
+        game.min_players,
+        game.max_players);
+      s = end_of_strn(s, &rest);
+    }
+
+    my_snprintf(s, rest,
+      "year=%d&"
+      "endyear=%d&"
+      "timeout=%d&",
+      game.year,
+      game.end_year,
+      game.timeout);
+    s = end_of_strn(s, &rest);
+
+    /* NOTE: send info for ALL players or none at all. */
+    if (get_num_human_and_ai_players() == 0) {
+      mystrlcpy(s, "dropplayers=1&", rest);
+      s = end_of_strn(s, &rest);
+    } else {
+      players_iterate(plr) {
+        char ai;
+
+        if (!is_barbarian(plr)) {
+         /* Fixme: how should metaserver handle multi-connects?
+          * Uses player_addr_hack() for now.
+          */
+         my_snprintf(s, rest,
+           "playername[]=%s&",
+           my_url_encode(plr->name));
+         s = end_of_strn(s, &rest);
+
+          if (server_state >= RUN_GAME_STATE) {
+           my_snprintf(s, rest,
+             "playernation[]=%s&",
+             my_url_encode(get_nation_name_plural(plr->nation)));
+           s = end_of_strn(s, &rest);
+         }
+
+         if (plr->ai.control) {
+           if (plr->ai.skill_level <= 3) {
+                ai = 'E';
+              } else if (plr->ai.skill_level <= 5) {
+                ai = 'N';
+              } else {
+                ai = 'H';
+              }
+         } else {
+           ai = 'P';
+         }
+
+         my_snprintf(s, rest,
+           "playerai[]=%c&"
+           "playerhost[]=%s&",
+           ai,
+           my_url_encode(player_addr_hack(plr)));
+         s = end_of_strn(s, &rest);
+       }
+      } players_iterate_end;
+    }
+  }
 
-  size = dio_output_used(&dout);
+  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);
 
-  dio_output_rewind(&dout);
-  dio_put_uint16(&dout, size);
+  printf("---\n");
+  fz_fclose(f);
 
-  my_writesocket(sockfd, buffer, size);
   return TRUE;
 }
 
@@ -157,21 +316,9 @@
 *************************************************************************/
 void server_close_udp(void)
 {
-  server_is_open = FALSE;
-
-  if(sockfd<=0)
-    return;
-  my_closesocket(sockfd);
-  sockfd=0;
-}
+  (void) send_server_info_to_metaserver(TRUE, FALSE, META_GOODBYE);
 
-/*************************************************************************
-...
-*************************************************************************/
-static void metaserver_failed(void)
-{
-  con_puts(C_METAERROR, _("Not reporting to the metaserver in this game."));
-  con_flush();
+  server_is_open = FALSE;
 }
 
 /*************************************************************************
@@ -179,54 +326,22 @@
 *************************************************************************/
 void server_open_udp(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 +349,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 +373,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       17 Sep 2004 22:49:10 -0000
@@ -20,12 +20,18 @@
  */
 
 #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/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);
@@ -34,7 +40,7 @@
 void server_close_udp(void);
 void server_open_udp(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     17 Sep 2004 22:49:10 -0000
@@ -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   17 Sep 2004 22:49:11 -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);
 
@@ -1606,7 +1605,7 @@
     server_open_udp(); /* 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  17 Sep 2004 22:49:11 -0000
@@ -497,7 +497,7 @@
 static void open_metaserver_connection(struct connection *caller)
 {
   server_open_udp();
-  if (send_server_info_to_metaserver(TRUE, FALSE)) {
+  if (send_server_info_to_metaserver(TRUE, FALSE, META_VERSION|META_COMMENT)) {
     notify_player(NULL, _("Open metaserver connection to [%s]."),
                  meta_addr_port());
   }
@@ -508,7 +508,7 @@
 **************************************************************************/
 static void close_metaserver_connection(struct connection *caller)
 {
-  if (send_server_info_to_metaserver(TRUE, TRUE)) {
+  if (send_server_info_to_metaserver(TRUE, TRUE, META_INFO)) {
     server_close_udp();
     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   17 Sep 2004 22:49:11 -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   17 Sep 2004 22:49:11 -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 */

[Prev in Thread] Current Thread [Next in Thread]