| t@@ -95,7 +95,8 @@ static void NewGameDialog(void);
static void StartGame(void);
static void EndGame(void);
static void UpdateMenus(void);
-static gboolean AuthDialog(HttpConnection *conn,gchar *realm);
+static void AuthDialog(HttpConnection *conn,
+ gboolean proxyauth,gchar *realm);
#ifdef NETWORKING
static void GetClientMessage(gpointer data,gint socket,
t@@ -2161,7 +2162,9 @@ static void CloseNewGameDia(GtkWidget *widget,
struct StartGameStruct *widgets) {
#ifdef NETWORKING
/* Terminate any existing connection attempts */
- ShutdownNetworkBuffer(&ClientData.Play->NetBuf);
+ if (ClientData.Play->NetBuf.status!=NBS_CONNECTED) {
+ ShutdownNetworkBuffer(&ClientData.Play->NetBuf);
+ }
if (widgets->MetaConn) {
CloseHttpConnection(widgets->MetaConn); widgets->MetaConn=NULL;
}
t@@ -3126,42 +3129,56 @@ void DisplaySpyReports(Player *Play) {
static void OKAuthDialog(GtkWidget *widget,GtkWidget *window) {
GtkWidget *userentry,*passwdentry;
gchar *username,*password;
+ gpointer proxy;
HttpConnection *conn;
- gboolean *retval;
+ proxy = gtk_object_get_data(GTK_OBJECT(window),"proxy");
userentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window),"username");
passwdentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window),
"password");
- retval = (gboolean *)gtk_object_get_data(GTK_OBJECT(window),"retval");
conn = (HttpConnection *)gtk_object_get_data(GTK_OBJECT(window),"httpconn");
- g_assert(userentry && passwdentry && retval && conn);
-
- *retval = TRUE;
+ g_assert(userentry && passwdentry && conn);
username = gtk_editable_get_chars(GTK_EDITABLE(userentry),0,-1);
password = gtk_editable_get_chars(GTK_EDITABLE(passwdentry),0,-1);
- SetHttpAuthentication(conn,username,password);
+ gtk_object_set_data(GTK_OBJECT(window),"authdone",GINT_TO_POINTER(TRUE));
+
+ if (!SetHttpAuthentication(conn,GPOINTER_TO_INT(proxy),username,password)) {
+ g_print("FIXME: Connect error on setauth\n");
+ }
g_free(username); g_free(password);
gtk_widget_destroy(window);
}
void DestroyAuthDialog(GtkWidget *widget,gpointer data) {
- gtk_main_quit();
+ HttpConnection *conn;
+ gpointer authdone,proxy;
+
+ authdone = gtk_object_get_data(GTK_OBJECT(widget),"authdone");
+ conn = (HttpConnection *)gtk_object_get_data(GTK_OBJECT(widget),"httpconn");
+ proxy = gtk_object_get_data(GTK_OBJECT(widget),"proxy");
+
+ if (authdone) {
+ g_print("Auth already done, thanks\n");
+ } else {
+ if (!SetHttpAuthentication(conn,GPOINTER_TO_INT(proxy),NULL,NULL)) {
+ g_print("FIXME: Connect error on unsetauth\n");
+ }
+ }
}
-gboolean AuthDialog(HttpConnection *conn,gchar *realm) {
+void AuthDialog(HttpConnection *conn,gboolean proxy,gchar *realm) {
GtkWidget *window,*button,*hsep,*vbox,*label,*entry,*table,*hbbox;
- gboolean retval=FALSE;
window=gtk_window_new(GTK_WINDOW_DIALOG);
gtk_signal_connect(GTK_OBJECT(window),"destroy",
GTK_SIGNAL_FUNC(DestroyAuthDialog),NULL);
- gtk_object_set_data(GTK_OBJECT(window),"retval",(gpointer)&retval);
+ gtk_object_set_data(GTK_OBJECT(window),"proxy",GINT_TO_POINTER(proxy));
gtk_object_set_data(GTK_OBJECT(window),"httpconn",(gpointer)conn);
- if (conn->proxyauth) {
+ if (proxy) {
gtk_window_set_title(GTK_WINDOW(window),
/* Title of dialog for authenticating with a proxy server */
_("Proxy Authentication Required"));
t@@ -3229,9 +3246,6 @@ gboolean AuthDialog(HttpConnection *conn,gchar *realm) {
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show_all(window);
-
- gtk_main();
- return retval;
}
#else |
| t@@ -44,6 +44,8 @@
#define WM_SOCKETDATA (WM_USER+100)
+static gint RecurseLevel=0;
+
static const gchar *WC_GTKSEP = "WC_GTKSEP";
static const gchar *WC_GTKVPANED = "WC_GTKVPANED";
static const gchar *WC_GTKHPANED = "WC_GTKHPANED";
t@@ -922,9 +924,13 @@ LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,UINT wParam,LONG lParam) {
}
break;
case WM_SOCKETDATA:
+/* Ignore network messages if in recursive message loops, to avoid dodgy
+ race conditions */
+ if (RecurseLevel<=1) {
/* Make any error available by the usual WSAGetLastError() mechanism */
- WSASetLastError(WSAGETSELECTERROR(lParam));
- DispatchSocketEvent((SOCKET)wParam,WSAGETSELECTEVENT(lParam));
+ WSASetLastError(WSAGETSELECTERROR(lParam));
+ DispatchSocketEvent((SOCKET)wParam,WSAGETSELECTEVENT(lParam));
+ }
break;
case WM_TIMER:
DispatchTimeoutEvent((UINT)wParam);
t@@ -963,6 +969,7 @@ void win32_init(HINSTANCE hInstance,HINSTANCE hPrevInstance,char *MainIcon) {
hInst=hInstance;
hFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
WindowList=NULL;
+ RecurseLevel=0;
if (!hPrevInstance) {
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
t@@ -2896,6 +2903,8 @@ void gtk_main() {
GtkWidget *widget;
HACCEL hAccel;
+ RecurseLevel++;
+
while (GetMessage(&msg,NULL,0,0)) {
MsgDone=FALSE;
for (list=WindowList;list && !MsgDone;list=g_slist_next(list)) {
t@@ -2913,6 +2922,7 @@ void gtk_main() {
DispatchMessage(&msg);
}
}
+ RecurseLevel--;
}
typedef struct _GtkSignal GtkSignal;
t@@ -4416,8 +4426,14 @@ void gtk_progress_bar_realize(GtkWidget *widget) {
gint GtkMessageBox(GtkWidget *parent,const gchar *Text,
const gchar *Title,gint Options) {
- return MessageBox(parent && parent->hWnd ? parent->hWnd : NULL,
- Text,Title,Options);
+ gint retval;
+
+ RecurseLevel++;
+ retval = MessageBox(parent && parent->hWnd ? parent->hWnd : NULL,
+ Text,Title,Options);
+ RecurseLevel--;
+
+ return retval;
}
guint gtk_timeout_add(guint32 interval,GtkFunction function,gpointer data) { |
| t@@ -129,7 +129,9 @@ static void NetBufCallBack(NetworkBuffer *NetBuf) {
}
static void NetBufCallBackStop(NetworkBuffer *NetBuf) {
- if (NetBuf && NetBuf->CallBack) (*NetBuf->CallBack)(NetBuf,FALSE,FALSE);
+ if (NetBuf && NetBuf->CallBack) {
+ (*NetBuf->CallBack)(NetBuf,FALSE,FALSE);
+ }
}
static void InitConnBuf(ConnBuf *buf) {
t@@ -176,6 +178,8 @@ void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCallBack CallBack,
void SetNetworkBufferUserPasswdFunc(NetworkBuffer *NetBuf,
NBUserPasswd userpasswd) {
+/* Sets the function used to obtain a username and password for SOCKS5 */
+/* username/password authentication */
NetBuf->userpasswd=userpasswd;
}
t@@ -320,20 +324,28 @@ static void SocksAppendError(GString *str,LastError *error) {
static ErrorType ETSocks = { SocksAppendError };
static gboolean Socks5UserPasswd(NetworkBuffer *NetBuf) {
- gchar *user,*password;
- gchar *addpt;
- guint addlen;
- ConnBuf *conn;
-
if (!NetBuf->userpasswd) {
SetError(&NetBuf->error,&ETSocks,SEC_NOMETHODS);
return FALSE;
+ } else {
+/* Request a username and password (the callback function should in turn
+ call SendSocks5UserPasswd when it's done) */
+ NetBuf->sockstat = NBSS_USERPASSWD;
+ (*NetBuf->userpasswd)(NetBuf);
+ return TRUE;
}
- if (!(*NetBuf->userpasswd)(NetBuf,&user,&password)) {
+}
+
+gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user,
+ gchar *password) {
+ gchar *addpt;
+ guint addlen;
+ ConnBuf *conn;
+
+ if (!user || !password) {
SetError(&NetBuf->error,&ETSocks,SEC_USERCANCEL);
return FALSE;
}
-
conn=&NetBuf->negbuf;
addlen = 3 + strlen(user) + strlen(password);
addpt = ExpandWriteBuffer(conn,addlen);
t@@ -347,7 +359,6 @@ static gboolean Socks5UserPasswd(NetworkBuffer *NetBuf) {
strcpy(&addpt[3+strlen(user)],password);
g_free(user); g_free(password);
- NetBuf->sockstat = NBSS_USERPASSWD;
conn->DataPresent+=addlen;
/* If the buffer was empty before, we may need to tell the owner to check
t@@ -457,7 +468,10 @@ g_print("FIXME: SOCKS5 connect reply\n");
else replylen+=data[4]; /* FQDN */
data = GetWaitingData(NetBuf,replylen);
if (data) {
- g_print("FIXME: SOCKS5 sucessful connect\n");
+ g_print("FIXME: SOCKS5 successful connect\n");
+ if (addrtype==1) g_print("IPv4 address %d.%d.%d.%d\n",data[4],data[5],data[6],data[7]);
+ else if (addrtype==4) g_print("IPv6 address\n");
+ else g_print("FQDN\n");
NetBuf->status = NBS_CONNECTED;
g_free(data);
NetBufCallBack(NetBuf); /* status has changed */
t@@ -896,7 +910,6 @@ static void SendHttpRequest(HttpConnection *conn) {
conn->Tries++;
conn->StatusCode=0;
conn->Status=HS_CONNECTING;
- conn->authsupplied=FALSE;
text=g_string_new("");
t@@ -908,9 +921,14 @@ static void SendHttpRequest(HttpConnection *conn) {
if (conn->user && conn->password) {
userpasswd = g_strdup_printf("%s:%s",conn->user,conn->password);
- g_string_assign(text,conn->proxyauth ? "Proxy-Authenticate" :
- "Authorization");
- g_string_append(text,": Basic ");
+ g_string_assign(text,"Authorization: Basic ");
+ AddB64Enc(text,userpasswd);
+ g_free(userpasswd);
+ QueueMessageForSend(&conn->NetBuf,text->str);
+ }
+ if (conn->proxyuser && conn->proxypassword) {
+ userpasswd = g_strdup_printf("%s:%s",conn->proxyuser,conn->proxypassword);
+ g_string_assign(text,"Proxy-Authenticate: Basic ");
AddB64Enc(text,userpasswd);
g_free(userpasswd);
QueueMessageForSend(&conn->NetBuf,text->str);
t@@ -961,7 +979,6 @@ gboolean OpenHttpConnection(HttpConnection **connpt,gchar *HostName,
if (Body && Body[0]) conn->Body=g_strdup(Body);
conn->Port = Port;
conn->ProxyPort = ProxyPort;
- conn->user = conn->password = NULL;
*connpt = conn;
if (StartHttpConnect(conn)) {
t@@ -982,9 +999,10 @@ void CloseHttpConnection(HttpConnection *conn) {
g_free(conn->Body);
g_free(conn->RedirHost);
g_free(conn->RedirQuery);
- g_free(conn->realm);
g_free(conn->user);
g_free(conn->password);
+ g_free(conn->proxyuser);
+ g_free(conn->proxypassword);
g_free(conn);
}
t@@ -992,12 +1010,25 @@ gboolean IsHttpError(HttpConnection *conn) {
return IsError(&conn->NetBuf.error);
}
-void SetHttpAuthentication(HttpConnection *conn,gchar *user,gchar *password) {
- g_assert(conn && user && password);
- g_free(conn->user);
- g_free(conn->password);
- conn->user = g_strdup(user);
- conn->password = g_strdup(password);
+gboolean SetHttpAuthentication(HttpConnection *conn,gboolean proxy,
+ gchar *user,gchar *password) {
+ gchar **ptuser,**ptpassword;
+ g_assert(conn);
+ if (proxy) {
+ ptuser=&conn->proxyuser; ptpassword=&conn->proxypassword;
+ } else {
+ ptuser=&conn->user; ptpassword=&conn->password;
+ }
+ g_free(*ptuser); g_free(*ptpassword);
+ if (user && password) {
+ *ptuser = g_strdup(user);
+ *ptpassword = g_strdup(password);
+ } else {
+ *ptuser = *ptpassword = NULL;
+ }
+ conn->waitinput=FALSE;
+ if (conn->Status==HS_WAITCOMPLETE) return !HandleHttpCompletion(conn);
+ else return TRUE;
}
void SetHttpAuthFunc(HttpConnection *conn,HCAuthFunc authfunc) {
t@@ -1062,15 +1093,19 @@ 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]);
- conn->proxyauth=FALSE;
- if (conn->authfunc) conn->authsupplied=(*conn->authfunc)(conn,split[1]);
+ if (conn->authfunc) {
+ conn->waitinput=TRUE;
+ (*conn->authfunc)(conn,FALSE,split[1]);
+ }
/* Proxy-Authenticate is, strictly speaking, an HTTP/1.1 thing, but some
HTTP/1.0 proxies seem to support it anyway */
} else if (g_strcasecmp(split[0],"Proxy-Authenticate:")==0 &&
conn->StatusCode==407) {
g_print("FIXME: Proxy authentication %s required\n",split[1]);
- conn->proxyauth=TRUE;
- if (conn->authfunc) conn->authsupplied=(*conn->authfunc)(conn,split[1]);
+ if (conn->authfunc) {
+ conn->waitinput=TRUE;
+ (*conn->authfunc)(conn,TRUE,split[1]);
+ }
}
}
g_strfreev(split);
t@@ -1099,6 +1134,9 @@ gchar *ReadHttpResponse(HttpConnection *conn) {
break;
case HS_READBODY: /* At present, we do nothing special with the body */
break;
+ case HS_WAITCOMPLETE: /* Well, we shouldn't be here at all... */
+ g_free(msg); msg=NULL;
+ break;
}
return msg;
}
t@@ -1109,6 +1147,13 @@ gboolean HandleHttpCompletion(HttpConnection *conn) {
NBUserPasswd userpasswd;
gboolean retry=FALSE;
+/* If we're still waiting for authentication etc., then signal that the
+ connection shouldn't be closed yet, and go into the "WAITCOMPLETE" state */
+ if (conn->waitinput) {
+ conn->Status = HS_WAITCOMPLETE;
+ return FALSE;
+ }
+
if (conn->Tries>=5) {
g_print("FIXME: Number of tries exceeded\n");
return TRUE;
t@@ -1123,10 +1168,14 @@ gboolean HandleHttpCompletion(HttpConnection *conn) {
conn->RedirHost = conn->RedirQuery = NULL;
retry = TRUE;
}
- if (conn->authsupplied && conn->user && conn->password) {
+ if (conn->StatusCode==401 && conn->user && conn->password) {
g_print("Trying again with authentication\n");
retry = TRUE;
}
+ if (conn->StatusCode==407 && conn->proxyuser && conn->proxypassword) {
+ g_print("Trying again with proxy authentication\n");
+ retry = TRUE;
+ }
if (retry) {
CallBack=conn->NetBuf.CallBack; |
| t@@ -65,8 +65,7 @@ typedef struct _NetworkBuffer NetworkBuffer;
typedef void (*NBCallBack)(NetworkBuffer *NetBuf,gboolean Read,gboolean Write);
-typedef gboolean (*NBUserPasswd)(NetworkBuffer *NetBuf,
- gchar **user,gchar **password);
+typedef void (*NBUserPasswd)(NetworkBuffer *NetBuf);
/* Information about a SOCKS server */
typedef struct _SocksServer {
t@@ -114,12 +113,18 @@ struct _NetworkBuffer {
/* Keeps track of the progress of an HTTP connection */
typedef enum {
- HS_CONNECTING, HS_READHEADERS, HS_READSEPARATOR, HS_READBODY
+ HS_CONNECTING, /* Waiting for connect() to complete */
+ HS_READHEADERS, /* Reading HTTP headers */
+ HS_READSEPARATOR, /* Reading the header/body separator line */
+ HS_READBODY, /* Reading HTTP body */
+ HS_WAITCOMPLETE /* Done reading, now waiting for authentication etc.
+ before closing and/or retrying the connection */
} HttpStatus;
typedef struct _HttpConnection HttpConnection;
-typedef gboolean (*HCAuthFunc)(struct _HttpConnection *conn,gchar *realm);
+typedef void (*HCAuthFunc)(struct _HttpConnection *conn,
+ gboolean proxyauth,gchar *realm);
/* A structure used to keep track of an HTTP connection */
struct _HttpConnection {
t@@ -135,11 +140,12 @@ struct _HttpConnection {
gchar *RedirQuery; /* if non-NULL, the path to redirect to */
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 */
+ gboolean waitinput; /* TRUE if we're waiting for auth etc.
+ to be supplied */
+ gchar *user; /* The supplied username for HTTP auth */
+ gchar *password; /* The supplied password for HTTP auth */
+ gchar *proxyuser; /* The supplied username for HTTP proxy auth */
+ gchar *proxypassword; /* The supplied password for HTTP proxy auth */
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@@ -169,6 +175,8 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf);
void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *data);
gint CountWaitingMessages(NetworkBuffer *NetBuf);
gchar *GetWaitingMessage(NetworkBuffer *NetBuf);
+gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user,
+ gchar *password);
gboolean OpenHttpConnection(HttpConnection **conn,gchar *HostName,
unsigned Port,gchar *Proxy,unsigned ProxyPort,
t@@ -178,7 +186,8 @@ gboolean OpenHttpConnection(HttpConnection **conn,gchar *HostName,
void CloseHttpConnection(HttpConnection *conn);
gboolean IsHttpError(HttpConnection *conn);
gchar *ReadHttpResponse(HttpConnection *conn);
-void SetHttpAuthentication(HttpConnection *conn,gchar *user,gchar *password);
+gboolean SetHttpAuthentication(HttpConnection *conn,gboolean proxy,
+ gchar *user,gchar *password);
void SetHttpAuthFunc(HttpConnection *conn,HCAuthFunc authfunc);
gboolean HandleHttpCompletion(HttpConnection *conn);
|