tFunctional HTTP authentication for GTK+ client - 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 04aa8fc36d982da2256c181c63a833ca0cd5c52a
 (DIR) parent 88feb29ac0e7cbce3c3f4f1a9aaaaa84fb1e1d7f
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Fri,  5 Oct 2001 17:03:34 +0000
       
       Functional HTTP authentication for GTK+ client
       
       
       Diffstat:
         M src/network.c                       |      75 +++++++++++++++++++++++++++----
         M src/network.h                       |       3 +++
       
       2 files changed, 69 insertions(+), 9 deletions(-)
       ---
 (DIR) diff --git a/src/network.c b/src/network.c
       t@@ -435,10 +435,12 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf) {
        
        static void SendHttpRequest(HttpConnection *conn) {
           GString *text;
       +   char *userpasswd;
        
           conn->Tries++;
           conn->StatusCode=0;
           conn->Status=HS_CONNECTING;
       +   conn->authsupplied=FALSE;
        
           text=g_string_new("");
        
       t@@ -448,6 +450,14 @@ static void SendHttpRequest(HttpConnection *conn) {
        
           if (conn->Headers) QueueMessageForSend(&conn->NetBuf,conn->Headers);
        
       +   if (conn->user && conn->password) {
       +      userpasswd = g_strdup_printf("%s:%s",conn->user,conn->password);
       +      g_string_assign(text,"Authorization: Basic ");
       +      AddB64Enc(text,userpasswd);
       +      g_free(userpasswd);
       +      QueueMessageForSend(&conn->NetBuf,text->str);
       +   }
       +
           g_string_sprintf(text,"User-Agent: dopewars/%s",VERSION);
           QueueMessageForSend(&conn->NetBuf,text->str);
        
       t@@ -592,7 +602,7 @@ static void ParseHtmlHeader(gchar *line,HttpConnection *conn) {
            } else if (g_strcasecmp(split[0],"WWW-Authenticate:")==0 &&
                       conn->StatusCode==401) {
              g_print("FIXME: Authentication %s required\n",split[1]);
       -      if (conn->authfunc) (*conn->authfunc)(conn,split[1]);
       +      if (conn->authfunc) conn->authsupplied=(*conn->authfunc)(conn,split[1]);
            }
          }
          g_strfreev(split);
       t@@ -628,22 +638,31 @@ gchar *ReadHttpResponse(HttpConnection *conn) {
        gboolean HandleHttpCompletion(HttpConnection *conn) {
           NBCallBack CallBack;
           gpointer CallBackData;
       +   gboolean retry=FALSE;
       +
       +   if (conn->Tries>=5) {
       +      g_print("FIXME: Number of tries exceeded\n");
       +      return TRUE;
       +   }
       +
           if (conn->RedirHost) {
              g_print("Following redirect to %s\n",conn->RedirHost);
       -      CallBack=conn->NetBuf.CallBack;
       -      CallBackData=conn->NetBuf.CallBackData;
       -      ShutdownNetworkBuffer(&conn->NetBuf);
              g_free(conn->HostName); g_free(conn->Query);
              conn->HostName = conn->RedirHost;
              conn->Query = conn->RedirQuery;
              conn->Port = conn->RedirPort;
              conn->RedirHost = conn->RedirQuery = NULL;
       +      retry = TRUE;
       +   }
       +   if (conn->authsupplied && conn->user && conn->password) {
       +      g_print("Trying again with authentication\n");
       +      retry = TRUE;
       +   }
        
       -      if (conn->Tries>=5) {
       -         g_print("FIXME: Number of tries exceeded\n");
       -         return TRUE;
       -      }
       -
       +   if (retry) {
       +      CallBack=conn->NetBuf.CallBack;
       +      CallBackData=conn->NetBuf.CallBackData;
       +      ShutdownNetworkBuffer(&conn->NetBuf);
              if (StartHttpConnect(conn)) {
                 SendHttpRequest(conn);
                 SetNetworkBufferCallBack(&conn->NetBuf,CallBack,CallBackData);
       t@@ -729,4 +748,42 @@ gboolean FinishConnect(int fd,LastError *error) {
        #endif /* CYGWIN */
        }
        
       +static void AddB64char(GString *str,int c) {
       +   if (c<0) return;
       +   else if (c<26) g_string_append_c(str,c+'A');
       +   else if (c<52) g_string_append_c(str,c-26+'a');
       +   else if (c<62) g_string_append_c(str,c-52+'0');
       +   else if (c==62) g_string_append_c(str,'+');
       +   else g_string_append_c(str,'/');
       +}
       +
       +void AddB64Enc(GString *str,gchar *unenc) {
       +/* Adds the plain text string "unenc" to the end of the GString "str", */
       +/* using the Base64 encoding scheme.                                   */
       +   guint i;
       +   long value=0;
       +   if (!unenc || !str) return;
       +   for (i=0;i<strlen(unenc);i++) {
       +      value <<= 8;
       +      value |= (unsigned char)unenc[i];
       +      if (i % 3 == 2) {
       +        AddB64char(str,(value>>18)&0x3F);
       +        AddB64char(str,(value>>12)&0x3F);
       +        AddB64char(str,(value>>6)&0x3F);
       +        AddB64char(str,value&0x3F);
       +        value=0;
       +      }
       +   }
       +   if (i % 3 == 1) {
       +      AddB64char(str,(value>>2)&0x3F);
       +      AddB64char(str,(value<<4)&0x3F);
       +      g_string_append(str,"==");
       +   } else if (i % 3 == 2) {
       +      AddB64char(str,(value>>10)&0x3F);
       +      AddB64char(str,(value>>4)&0x3F);
       +      AddB64char(str,(value<<2)&0x3F);
       +      g_string_append_c(str,'=');
       +   }
       +}
       +
        #endif /* NETWORKING */
 (DIR) diff --git a/src/network.h b/src/network.h
       t@@ -104,6 +104,7 @@ struct _HttpConnection {
           unsigned RedirPort;    /* The port on the host to redirect to */
           HCAuthFunc authfunc;   /* Callback function for authentication */
           gboolean proxyauth;    /* TRUE if the authentication is with a proxy */
       +   gboolean authsupplied; /* TRUE if the request should be retried with auth */
           gchar *realm;          /* The realm for basic HTTP authentication */
           gchar *user;           /* The supplied username */
           gchar *password;       /* The supplied password */
       t@@ -160,6 +161,8 @@ void SetReuse(int sock);
        void SetBlocking(int sock,gboolean blocking);
        #endif
        
       +void AddB64Enc(GString *str,gchar *unenc);
       +
        #endif /* NETWORKING */
        
        #endif /* __NETWORK_H__ */