tCode added for automatic following of HTTP redirects - vaccinewars - be a doctor and try to vaccinate the world
 (HTM) git clone git://src.adamsgaard.dk/vaccinewars
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit be798e2756ceb84bf960d15ac83dd1dbd71a0daa
 (DIR) parent 322ccf9499188e8f8bf6bd047e326d5fe57cc197
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Thu, 13 Sep 2001 20:21:37 +0000
       
       Code added for automatic following of HTTP redirects
       
       
       Diffstat:
         M src/message.c                       |     109 ++++++++++++++++++++++---------
         M src/message.h                       |       2 ++
         M src/serverside.c                    |       8 ++++----
       
       3 files changed, 84 insertions(+), 35 deletions(-)
       ---
 (DIR) diff --git a/src/message.c b/src/message.c
       t@@ -629,45 +629,22 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf) {
           return TRUE;
        }
        
       -HttpConnection *OpenHttpConnection(gchar *HostName,unsigned Port,
       -                                   gchar *Proxy,unsigned ProxyPort,
       -                                   gchar *Method,gchar *Query,
       -                                   gchar *Headers,gchar *Body) {
       -   HttpConnection *conn;
       -   gchar *ConnectHost;
       -   unsigned ConnectPort;
       +static void SendHttpRequest(HttpConnection *conn) {
           GString *text;
       -   g_assert(HostName && Method && Query);
       -
       -   conn=g_new0(HttpConnection,1);
       -   InitNetworkBuffer(&conn->NetBuf,'\n','\r');
       -   conn->HostName=g_strdup(HostName);
       -   if (Proxy && Proxy[0]) conn->Proxy=g_strdup(Proxy);
       -   conn->Method=g_strdup(Method);
       -   conn->Query=g_strdup(Query);
       -   if (Headers && Headers[0]) conn->Headers=g_strdup(Headers);
       -   if (Body && Body[0]) conn->Body=g_strdup(Body);
       -   conn->Port = Port;
       -   conn->ProxyPort = ProxyPort;
        
       -   if (conn->Proxy) {
       -      ConnectHost=conn->Proxy; ConnectPort=conn->ProxyPort;
       -   } else {
       -      ConnectHost=conn->HostName; ConnectPort=conn->Port;
       -   }
       -      
       -   if (!StartNetworkBufferConnect(&conn->NetBuf,ConnectHost,ConnectPort)) {
       -      CloseHttpConnection(conn);
       -      return NULL;
       -   }
           conn->Tries++;
           conn->StatusCode=0;
           conn->Status=HS_CONNECTING;
        
           text=g_string_new("");
        
       -   g_string_sprintf(text,"%s http://%s:%u%s HTTP/1.0",
       -                    conn->Method,conn->HostName,conn->Port,conn->Query);
       +   if (conn->Redirect) {
       +      g_string_sprintf(text,"%s %s HTTP/1.0",conn->Method,conn->Redirect);
       +      g_free(conn->Redirect); conn->Redirect=NULL;
       +   } else {
       +      g_string_sprintf(text,"%s http://%s:%u%s HTTP/1.0",
       +                       conn->Method,conn->HostName,conn->Port,conn->Query);
       +   }
           QueueMessageForSend(&conn->NetBuf,text->str);
        
           if (conn->Headers) QueueMessageForSend(&conn->NetBuf,conn->Headers);
       t@@ -681,6 +658,45 @@ HttpConnection *OpenHttpConnection(gchar *HostName,unsigned Port,
           if (conn->Body) QueueMessageForSend(&conn->NetBuf,conn->Body);
        
           g_string_free(text,TRUE);
       +}
       +
       +static gboolean StartHttpConnect(HttpConnection *conn) {
       +   gchar *ConnectHost;
       +   unsigned ConnectPort;
       +
       +   if (conn->Proxy) {
       +      ConnectHost=conn->Proxy; ConnectPort=conn->ProxyPort;
       +   } else {
       +      ConnectHost=conn->HostName; ConnectPort=conn->Port;
       +   }
       +      
       +   if (!StartNetworkBufferConnect(&conn->NetBuf,ConnectHost,ConnectPort)) {
       +      CloseHttpConnection(conn);
       +      return FALSE;
       +   }
       +   return TRUE;
       +}
       +
       +HttpConnection *OpenHttpConnection(gchar *HostName,unsigned Port,
       +                                   gchar *Proxy,unsigned ProxyPort,
       +                                   gchar *Method,gchar *Query,
       +                                   gchar *Headers,gchar *Body) {
       +   HttpConnection *conn;
       +   g_assert(HostName && Method && Query);
       +
       +   conn=g_new0(HttpConnection,1);
       +   InitNetworkBuffer(&conn->NetBuf,'\n','\r');
       +   conn->HostName=g_strdup(HostName);
       +   if (Proxy && Proxy[0]) conn->Proxy=g_strdup(Proxy);
       +   conn->Method=g_strdup(Method);
       +   conn->Query=g_strdup(Query);
       +   if (Headers && Headers[0]) conn->Headers=g_strdup(Headers);
       +   if (Body && Body[0]) conn->Body=g_strdup(Body);
       +   conn->Port = Port;
       +   conn->ProxyPort = ProxyPort;
       +
       +   if (!StartHttpConnect(conn)) return NULL;
       +   SendHttpRequest(conn);
        
           return conn;
        }
       t@@ -707,6 +723,7 @@ void CloseHttpConnection(HttpConnection *conn) {
           g_free(conn->Query);
           g_free(conn->Headers);
           g_free(conn->Body);
       +   g_free(conn->Redirect);
           g_free(conn);
        }
        
       t@@ -726,6 +743,18 @@ gchar *ReadHttpResponse(HttpConnection *conn) {
                 break;
              case HS_READHEADERS:
                 if (msg[0]==0) conn->Status=HS_READSEPARATOR;
       +         else {
       +            split=g_strsplit(msg," ",1);
       +            if (split[0] && split[1]) {
       +               if (conn->StatusCode==302 && strcmp(split[0],"Location:")==0) {
       +                  g_print("Redirect to %s\n",split[1]);
       +                  g_free(conn->Redirect);
       +                  conn->Redirect = g_strdup(split[1]);
       +               }
       +/*             g_print("Header %s (value %s) read\n",split[0],split[1]);*/
       +            }
       +            g_strfreev(split);
       +         }
                 break;
              case HS_READSEPARATOR:
                 conn->Status=HS_READBODY;
       t@@ -736,6 +765,24 @@ gchar *ReadHttpResponse(HttpConnection *conn) {
           return msg;
        }
        
       +gboolean HandleHttpCompletion(HttpConnection *conn) {
       +   NBCallBack CallBack;
       +   gpointer CallBackData;
       +   if (conn->Redirect) {
       +      g_print("Following redirect\n");
       +      CallBack=conn->NetBuf.CallBack;
       +      CallBackData=conn->NetBuf.CallBackData;
       +      ShutdownNetworkBuffer(&conn->NetBuf);
       +      if (StartHttpConnect(conn)) {
       +         SendHttpRequest(conn);
       +         SetNetworkBufferCallBack(&conn->NetBuf,CallBack,CallBackData);
       +         return FALSE;
       +      }
       +   }
       +   CloseHttpConnection(conn);
       +   return TRUE;
       +}
       +
        gboolean HandleWaitingMetaServerData(HttpConnection *conn) {
           gchar *msg;
           ServerData *NewServer;
 (DIR) diff --git a/src/message.h b/src/message.h
       t@@ -87,6 +87,7 @@ typedef struct _HttpConnection {
           gchar *Query;          /* e.g. the path of the desired webpage */
           gchar *Headers;        /* if non-NULL, e.g. Content-Type */
           gchar *Body;           /* if non-NULL, data to send */
       +   gchar *Redirect;       /* if non-NULL, a URL to redirect to */
           NetworkBuffer NetBuf;  /* The actual network connection itself */
           gint Tries;            /* Number of requests actually sent so far */
           gint StatusCode;       /* 0=no status yet, otherwise an HTTP status code */
       t@@ -132,6 +133,7 @@ HttpConnection *OpenHttpConnection(gchar *HostName,unsigned Port,
        HttpConnection *OpenMetaHttpConnection(void);
        void CloseHttpConnection(HttpConnection *conn);
        gchar *ReadHttpResponse(HttpConnection *conn);
       +gboolean HandleHttpCompletion(HttpConnection *conn);
        gboolean HandleWaitingMetaServerData(HttpConnection *conn);
        void ClearServerList(void);
        #endif /* NETWORKING */
 (DIR) diff --git a/src/serverside.c b/src/serverside.c
       t@@ -893,9 +893,9 @@ void ServerLoop() {
                       g_free(buf);
                    }
                 }
       -         if (!DoneOK) {
       +         if (!DoneOK && HandleHttpCompletion(MetaConn)) {
                    dopelog(4,"MetaServer: (closed)\n");
       -            CloseHttpConnection(MetaConn); MetaConn=NULL;
       +            MetaConn=NULL;
                    if (IsServerShutdown()) break;
                 }
              }
       t@@ -1010,9 +1010,9 @@ void GuiHandleMeta(gpointer data,gint socket,GdkInputCondition condition) {
                 g_free(buf);
              }
           }
       -   if (!DoneOK) {
       +   if (!DoneOK && HandleHttpCompletion(MetaConn)) {
              dopelog(4,"MetaServer: (closed)\n");
       -      CloseHttpConnection(MetaConn); MetaConn=NULL;
       +      MetaConn=NULL;
              if (IsServerShutdown()) GuiQuitServer();
           }
        }