diff --git a/mozilla/network/main/mkgeturl.c b/mozilla/network/main/mkgeturl.c index 6048b555869..53c70028435 100644 --- a/mozilla/network/main/mkgeturl.c +++ b/mozilla/network/main/mkgeturl.c @@ -3143,6 +3143,53 @@ redo_load_switch: /* come here on file/ftp retry */ #endif } +/* forward declaration */ +PUBLIC void NET_ResumeHTTP (ActiveEntry *, PRBool); + + +/* this thing is a hack that will allow http streams + waiting on passwd auth to resume XXX */ +PUBLIC void NET_ResumeWithAuth (void *closure) +{ + XP_List * iter = NULL; + ActiveEntry * tmpEntry = NULL; + NET_AuthClosure *auth_closure = (char *) closure; + + /* check to see if our entry is in the list */ + if (XP_ListIsEmpty(net_EntryList)) { + TRACEMSG (("NET_ResumeWithAuth: no list! we're busted ...")); + return; + } + iter = net_EntryList; + + while (tmpEntry = (ActiveEntry *) XP_ListNextObject(iter)) { + if (tmpEntry == (ActiveEntry *) auth_closure->_private) { + break; + } else { + return; + } + } + + if (auth_closure && auth_closure->pass && *auth_closure->pass) { + + TRACEMSG (("NET_ResumeWithAuth: auth succeeded: %s", tmpEntry->URL_s->address)); + /* now update the user/pass */ + tmpEntry->URL_s->username = PL_strdup (auth_closure->user); + tmpEntry->URL_s->password = PL_strdup (auth_closure->pass); + + /* now try it again */ + NET_ResumeHTTP(tmpEntry, PR_TRUE); + + } else { + TRACEMSG (("NET_ResumeWithAuth(): auth failed: %s", tmpEntry->URL_s->address)); + NET_ResumeHTTP(tmpEntry, PR_FALSE); + } + + /* now free the closure struct */ + PR_Free(auth_closure); + return; +} + /* process_net is called from the client's main event loop and * causes connections to be read and processed. Multiple * connections can be processed simultaneously. @@ -3461,7 +3508,7 @@ PUBLIC int NET_ProcessNet (PRFileDesc *ready_fd, int fd_type) { PR_Free(tmpEntry); /* free the now non active entry */ } /* end if rv < 0 */ - + TRACEMSG(("Leaving process net with %d items in list", XP_ListCount(net_EntryList))); diff --git a/mozilla/network/module/nsStubContext.cpp b/mozilla/network/module/nsStubContext.cpp index fe2150f22b4..b6318a0a3d9 100644 --- a/mozilla/network/module/nsStubContext.cpp +++ b/mozilla/network/module/nsStubContext.cpp @@ -202,15 +202,150 @@ char *stub_Prompt(MWContext *context, return result; } -PRIVATE XP_Bool -stub_PromptUsernameAndPassword(MWContext *context, +#include "nsIComponentManager.h" +#include "nsIBlockingNotification.h" +#include "nsAppShellCIDs.h" +#include "plevent.h" +#include "nsXPComFactory.h" + +static NS_DEFINE_IID(kProtocolHelperCID, NS_PROTOCOL_HELPER_CID); +// static NS_DEFINE_IID(kDefaultNotificationCID, NS_DEFAULT_NOTIFICATION_CID); + +static NS_DEFINE_IID(kIBlockingNotificationObserverIID, + NS_IBLOCKINGNOTIFICATION_OBSERVER_IID); +static NS_DEFINE_IID(kIBlockingNotificationIID, NS_IBLOCKINGNOTIFICATION_IID); + +/*-------------------- nsDefaultNotification ----------------------------*/ + +// our notification object +class nsDefaultNotification : public nsIBlockingNotification +{ +public: + nsDefaultNotification(); + + /* nsISupports interface... */ + NS_DECL_ISUPPORTS + + /* nsIBlockingNotification interface... */ + NS_IMETHOD IsBlocked(nsIURL *aURL, PRBool *aResult); + NS_IMETHOD Resume(nsIURL *aUrl, void *aExtraInfo); +}; + +nsDefaultNotification::nsDefaultNotification() +{ + NS_INIT_REFCNT(); +} + +/* + * Implementations of nsISupports interface methods... + */ +NS_IMPL_ADDREF(nsDefaultNotification); +NS_IMPL_RELEASE(nsDefaultNotification); +NS_IMPL_QUERY_INTERFACE(nsDefaultNotification, kIBlockingNotificationIID); + +NS_IMETHODIMP +nsDefaultNotification::IsBlocked(nsIURL *aURL, PRBool *aResult) +{ + nsresult rv = NS_NOTIFY_BLOCKED; + return rv; +} + +NS_IMETHODIMP +nsDefaultNotification::Resume(nsIURL *aURL, void *aExtraInfo) +{ + nsresult rv = NS_NOTIFY_SUCCEEDED; + NET_ResumeWithAuth((void *) aExtraInfo); + return rv; +} + +/*--------------------------------------------------------------*/ + +/* forward declaration */ +class nsDefaultNotification; + +NS_DEF_FACTORY(DefaultNotification,nsDefaultNotification) + +nsresult NS_NewDefaultNotificationFactory(nsIFactory** aResult) +{ + nsresult rv = NS_OK; + nsIFactory* inst; + + inst = new nsDefaultNotificationFactory; + if (nsnull == inst) { + rv = NS_ERROR_OUT_OF_MEMORY; + } + else { + NS_ADDREF(inst); + } + *aResult = inst; + return rv; +} + +/*--------------------------------------------------------------*/ + + +#if 0 +PRIVATE XP_Bool +stub_PromptUsernameAndPassword(MWContext *context, + const char *msg, + char **username, + char **password, + void *closure) +{ + nsIBlockingNotificationObserver *helper; + nsIBlockingNotification *caller; + nsConnectionInfo *pConn = nsnull; + URL_Struct *URL_s = context->modular_data; + nsIURL *base = nsnull; + nsresult rv; + + printf ("stub_PromptUsernameAndPassword()\n"); + + /* Access the nsConnectionInfo object off of the URL Struct fe_data */ + if ((nsnull != URL_s) && (nsnull != URL_s->fe_data)) { + pConn = (nsConnectionInfo *)URL_s->fe_data; + } + + // create an object that calls Resume() XXX + rv = nsComponentManager::CreateInstance(kProtocolHelperCID, nsnull, kIBlockingNotificationIID, (void**)&caller); + if (NS_FAILED(rv)) { + return FALSE; + } + // build an nsIURL + rv = NS_NewURL(&base, URL_s->address); + if (NS_FAILED(rv)) { + return FALSE; + } + + rv = nsComponentManager::CreateInstance(kProtocolHelperCID, nsnull, kIBlockingNotificationObserverIID, (void**)&helper); + if (NS_SUCCEEDED(rv)) { + rv = helper->Notify(caller, base, pConn->mRequestingThread, 0, closure); + NS_RELEASE(helper); + } else { + return FALSE; + } + *username = nsnull; + *password = nsnull; + + // XXX we can't return TRUE anymore, since the ProtocolHelper is + // is still waiting for the user ... + // return TRUE; + + return FALSE; +} +#endif /* 0 */ + + +PRIVATE XP_Bool _stub_PromptUsernameAndPassword(MWContext *context, const char *msg, char **username, - char **password) + char **password, + void *closure) { nsINetSupport *ins; XP_Bool bResult = FALSE; +#if 0 if (nsnull != (ins = getNetSupport(context->modular_data))) { nsAutoString str(msg); nsAutoString userStr(*username); @@ -225,27 +360,37 @@ stub_PromptUsernameAndPassword(MWContext *context, } /* No nsINetSupport interface... */ - else { + else +#endif /* 0 */ + { + NET_AuthClosure *auth_closure = (NET_AuthClosure *) closure; char buf[256]; + char *tmp_user = *username; + char *tmp_pass = *password; printf("%s\n", msg); - printf("%cUser (default=%s): ", '\007', *username); + printf("%cUser (default=%s): ", '\007', tmp_user); fgets(buf, sizeof buf, stdin); if (strlen(buf)) { - *username = PL_strdup(buf); + tmp_user = PL_strdup(buf); + tmp_user[strlen(tmp_user)-1] = '\0'; } - printf("%cPassword (default=%s): ", '\007', *password); + printf("%cPassword (default=%s): ", '\007', tmp_pass); fgets(buf, sizeof buf, stdin); if (strlen(buf)) { - *password = PL_strdup(buf); + tmp_pass = PL_strdup(buf); + tmp_pass[strlen(tmp_pass)-1] = '\0'; } - if (**username) { - bResult = TRUE; + if (tmp_user) { + bResult = FALSE; /* XXX false because the callback will finalize */ + auth_closure->user = tmp_user; + auth_closure->pass = tmp_pass; + NET_ResumeWithAuth (closure); } else { - PR_FREEIF(*username); - PR_FREEIF(*password); + PR_FREEIF(tmp_user); + PR_FREEIF(tmp_pass); } } @@ -284,6 +429,18 @@ char *stub_PromptPassword(MWContext *context, return result; } +extern "C" XP_Bool +stub_PromptUsernameAndPassword(MWContext *context, + const char *msg, + char **username, + char **password, + void *closure) +{ + return _stub_PromptUsernameAndPassword(context, msg, + username, password, + closure); +} + PRIVATE void stub_GraphProgressInit(MWContext *context, URL_Struct *URL_s, int32 content_length) @@ -660,7 +817,7 @@ unsigned int stub_is_write_ready(NET_StreamClass *stream) { nsresult errorCode; PRUint32 free_space = 0; - URL_Struct *URL_s = (URL_Struct *)stream->data_object; + /* URL_Struct *URL_s = (URL_Struct *)stream->data_object; */ nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); errorCode = pConn->pNetStream->GetAvailableSpace(&free_space); @@ -696,7 +853,6 @@ NET_NGLayoutConverter(FO_Present_Types format_out, MWContext *context) { NET_StreamClass *stream = NULL; - PRBool bSuccess = PR_TRUE; /* * Only create a stream if an nsConnectionInfo object is diff --git a/mozilla/network/protocol/http/mkaccess.c b/mozilla/network/protocol/http/mkaccess.c index 0fba774d440..74b0f55b2c4 100644 --- a/mozilla/network/protocol/http/mkaccess.c +++ b/mozilla/network/protocol/http/mkaccess.c @@ -520,7 +520,8 @@ NET_AskForAuthString(MWContext *context, URL_Struct * URL_s, char * authenticate, char * prot_template, - Bool already_sent_auth) + Bool already_sent_auth, + void *closure) { static PRBool first_time=TRUE; net_AuthStruct *prev_auth; @@ -796,6 +797,10 @@ NET_AskForAuthString(MWContext *context, /* if the password is filled in then the username must * be filled in already. */ + /* 4/6/99 -- with the new async dialogs, we will only enter this + statement the first time through; afterward, we will have the + user and pass via NET_ResumeWithAuth() + */ if(!password || re_authorize) { XP_Bool remember_password = FALSE; @@ -811,6 +816,7 @@ NET_AskForAuthString(MWContext *context, NET_Progress(context, XP_GetString( XP_CONNECT_PLEASE_ENTER_PASSWORD_FOR_HOST) ); +#if 0 #if defined(SingleSignon) /* prefill prompt with previous username/passwords if any * this returns 1 if user pressed OK, or 0 if they Canceled @@ -827,6 +833,16 @@ NET_AskForAuthString(MWContext *context, (context, buf, &username, &password, &remember_password, NET_IsURLSecure(URL_s->address)); #endif +#else + { + NET_AuthClosure * authclosure = (NET_AuthClosure *) closure; + + /* the new multi-threaded case -- we return asynchronously */ + authclosure->msg = PL_strdup (buf); + status = stub_PromptUsernameAndPassword + (context, buf, &username, &password, closure); + } +#endif PR_Free(buf); } else { @@ -836,6 +852,10 @@ NET_AskForAuthString(MWContext *context, PR_Free(host); if(!status) { + /* XXX now we have FALSE == WAIT_FOR_AUTH */ + return(NET_WAIT_FOR_AUTH); + +#ifdef notused /* with async dialogs, we never have a user/pass here */a TRACEMSG(("User canceled login!!!")); /* if the paths are exact and the user cancels @@ -847,6 +867,7 @@ NET_AskForAuthString(MWContext *context, PR_FREEIF(password); PR_FREEIF(new_address); return(NET_AUTH_FAILED_DISPLAY_DOCUMENT); +#endif /* notused */ } else if(!username || !password) { @@ -3663,7 +3684,8 @@ PUBLIC PRBool NET_AskForProxyAuth(MWContext * context, char * proxy_addr, char * pauth_params, - PRBool already_sent_auth) + PRBool already_sent_auth, + void * closure) { net_AuthStruct * prev; PRBool new_entry = FALSE; @@ -3758,6 +3780,7 @@ NET_AskForProxyAuth(MWContext * context, PR_snprintf(buf, len*sizeof(char), XP_GetString( XP_PROXY_AUTH_REQUIRED_FOR ), prev->realm, proxy_addr); NET_Progress(context, XP_GetString( XP_CONNECT_PLEASE_ENTER_PASSWORD_FOR_PROXY ) ); +#if 0 #if defined(SingleSignon) /* prefill prompt with previous username/passwords if any */ len = SI_PromptUsernameAndPassword @@ -3765,6 +3788,11 @@ NET_AskForProxyAuth(MWContext * context, #else len = FE_PromptUsernameAndPassword (context, buf, &username, &password); +#endif +#else + /* the new multi-thread case -- we return with out user/pass */ + len = stub_PromptUsernameAndPassword + (context, buf, &username, &password, closure); #endif PR_Free(buf); } @@ -3775,8 +3803,12 @@ NET_AskForProxyAuth(MWContext * context, if (!len) { + TRACEMSG(("Waiting for user auth")); + return FALSE; +#if notused TRACEMSG(("User canceled login!!!")); return FALSE; +#endif /* notused */ } else if (!username || !password) { @@ -5618,6 +5650,7 @@ NET_DisplayCookieInfoAsHTML(MWContext * context) net_DisplayCookieInfoAsHTML(context, NULL); } +#if 0 #ifdef XP_MAC /* pinkerton - reset optimization state (see above) */ #pragma global_optimizer reset @@ -5625,7 +5658,8 @@ NET_DisplayCookieInfoAsHTML(MWContext * context) #else PUBLIC void -NET_DisplayCookieInfoAsHTML(MWContext * context) +NET_DisplayCookieInfoAsHTML(ActiveEntry *cur_entry) { } #endif +#endif /* 0 */ diff --git a/mozilla/network/protocol/http/mkaccess.h b/mozilla/network/protocol/http/mkaccess.h index 8e0a33570ce..6a3acf10af9 100644 --- a/mozilla/network/protocol/http/mkaccess.h +++ b/mozilla/network/protocol/http/mkaccess.h @@ -34,7 +34,8 @@ extern Bool NET_AskForAuthString(MWContext * context, URL_Struct *URL_s, char * authenticate, char * prot_template, - Bool already_sent_auth); + Bool already_sent_auth, + void * closure); /* returns a authorization string if one is required, otherwise * returns NULL @@ -58,7 +59,8 @@ PUBLIC PRBool NET_AskForProxyAuth(MWContext * context, char * proxy_addr, char * pauth_params, - PRBool already_sent_auth); + PRBool already_sent_auth, + void * closure); MODULE_PRIVATE int PR_CALLBACK NET_CookieBehaviorPrefChanged(const char * newpref, void * data); diff --git a/mozilla/network/protocol/http/mkhttp.c b/mozilla/network/protocol/http/mkhttp.c index 49ee8c17194..d2d84f0d07e 100644 --- a/mozilla/network/protocol/http/mkhttp.c +++ b/mozilla/network/protocol/http/mkhttp.c @@ -1,3 +1,4 @@ + /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License @@ -128,7 +129,6 @@ PRIVATE XP_List * http_connection_list=0; PRIVATE IdentifyMeEnum http_identification_method = DoNotIdentifyMe; PRIVATE Bool sendRefererHeader=TRUE; - PUBLIC const HTTP_Version DEFAULT_VERSION = ONE_POINT_ONE; PRIVATE const char *VERSION_STRING_ONE_ONE = "HTTP/1.1"; PRIVATE const char *VERSION_STRING_ONE_ZERO = "HTTP/1.0"; @@ -139,6 +139,8 @@ PRIVATE const char *VERSION_STRING_ONE_ZERO = "HTTP/1.0"; typedef enum { HTTP_START_CONNECT, HTTP_FINISH_CONNECT, + HTTP_WAIT_FOR_AUTH, + HTTP_RESUME_WITH_AUTH, HTTP_SEND_PROXY_TUNNEL_REQUEST, HTTP_BEGIN_UPLOAD_FILE, HTTP_SEND_REQUEST, @@ -2409,7 +2411,10 @@ net_revert_post_data(ActiveEntry * ce) } } } - + +/* forward declaration */ +PRIVATE int net_finish_setup_http_stream(ActiveEntry * ce); + /* sets up the stream and performs special actions like redirect and * retry on authorization * @@ -2418,10 +2423,10 @@ net_revert_post_data(ActiveEntry * ce) PRIVATE int net_setup_http_stream(ActiveEntry * ce) { HTTPConData * cd = (HTTPConData *)ce->con_data; + NET_AuthClosure * auth_closure; XP_Bool need_to_do_again = FALSE; - MWContext * stream_context; - TRACEMSG(("NET_ProcessHTTP: setting up stream")); + TRACEMSG(("NET_ProcessHTTP: setting up stream: %s", ce->URL_s->address)); /* save this since it can be changed in lots * of places. This will be used for graph progress @@ -2487,24 +2492,43 @@ net_setup_http_stream(ActiveEntry * ce) { if(cd->authorization_required) { /* clear to prevent tight loop */ int status; + NET_ClearReadSelect(ce->window_id, cd->connection->sock); #if defined(SMOOTH_PROGRESS) PM_Suspend(ce->window_id, ce->URL_s); #endif + /* tuck the ce away for the auth callback */ + /* set up the auth closure struct for the password dialog */ + auth_closure = PR_NEWZAP(NET_AuthClosure); + if (!auth_closure) { + return(MK_INTERRUPTED); + } + + auth_closure->_private = (void *) ce; + auth_closure->msg = NULL; + auth_closure->user = NULL; + auth_closure->pass = NULL; + status = NET_AskForAuthString(ce->window_id, ce->URL_s, ce->URL_s->authenticate, ce->URL_s->protection_template, - cd->sent_authorization); + cd->sent_authorization, + (void *) auth_closure); #if defined(SMOOTH_PROGRESS) PM_Resume(ce->window_id, ce->URL_s); #endif - if(status == NET_RETRY_WITH_AUTH) + if (status == NET_RETRY_WITH_AUTH) { need_to_do_again = TRUE; + } else if (status == NET_WAIT_FOR_AUTH) { + if (!ce->URL_s->password) + cd->next_state = HTTP_WAIT_FOR_AUTH; + return(0); + } else ce->URL_s->dont_cache = TRUE; @@ -2554,12 +2578,26 @@ net_setup_http_stream(ActiveEntry * ce) { PM_Suspend(ce->window_id, ce->URL_s); #endif - if(NET_AskForProxyAuth(ce->window_id, - proxyServer, - ce->URL_s->proxy_authenticate, - cd->sent_proxy_auth)) + /* tuck the ce away for the auth callback */ + /* set up the auth closure struct for the password dialog */ + auth_closure = PR_NEWZAP(NET_AuthClosure); + if (!auth_closure) { + return(MK_INTERRUPTED); + } + + auth_closure->_private = (void *) ce; + auth_closure->msg = NULL; + auth_closure->user = NULL; + auth_closure->pass = NULL; + + if(NET_AskForProxyAuth(ce->window_id, + proxyServer, + ce->URL_s->proxy_authenticate, + cd->sent_proxy_auth, + (void *) auth_closure)) { need_to_do_again = TRUE; - else + TRACEMSG(("NET_AskForProxyAuth(): need_to_do_again: %s", ce->URL_s->address)); + } else ce->URL_s->dont_cache = TRUE; #if defined(SMOOTH_PROGRESS) @@ -2599,7 +2637,35 @@ net_setup_http_stream(ActiveEntry * ce) { return(0); /* continue */ - } else if (cd->doing_redirect && ce->URL_s->redirecting_url && + } + + /* Now finish stream setup. Setup needs to be broken in half + 'cuz in the case of modal dialogs, we need to wait for username + and password, then return to finish */ + return (ce->status = net_finish_setup_http_stream(ce)); +} + +PUBLIC void +NET_ResumeHTTP(ActiveEntry * ce, PRBool resume) +{ + HTTPConData * cd = (HTTPConData *) ce->con_data; + + TRACEMSG (("NET_ResumeHTTP: %s", ce->URL_s->address)); + if (resume) + cd->next_state = HTTP_SETUP_STREAM; + else + cd->next_state = HTTP_DONE; + + return; +} + +PRIVATE int +net_finish_setup_http_stream(ActiveEntry * ce) +{ + HTTPConData * cd = (HTTPConData *)ce->con_data; + MWContext * stream_context; + + if (cd->doing_redirect && ce->URL_s->redirecting_url && /* try and prevent a circular loop. wont work for dual doc loop */ PL_strcmp(ce->URL_s->redirecting_url, ce->URL_s->address)) { @@ -3438,6 +3504,14 @@ net_ProcessHTTP (ActiveEntry *ce) switch(cd->next_state) { + case HTTP_WAIT_FOR_AUTH: + TRACEMSG (("HTTP_WAIT_FOR_AUTH: %s", ce->URL_s->address)); + cd->pause_for_read = TRUE; + break; + case HTTP_RESUME_WITH_AUTH: + TRACEMSG (("HTTP_RESUME_WITH_AUTH: %s", ce->URL_s->address)); + ce->status = net_finish_setup_http_stream(ce); + break; case HTTP_START_CONNECT: ce->status = net_start_http_connect(ce); break;