/* -*- 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 * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* * Cross platform html dialogs * * */ #include "xp.h" #include "fe_proto.h" #include "seccomon.h" #include "net.h" #include "htmldlgs.h" #include "xpgetstr.h" #include "shist.h" #include "prlog.h" #include "libmocha.h" #include "prclist.h" extern int XP_SEC_CANCEL; extern int XP_SEC_OK; extern int XP_SEC_CONTINUE; extern int XP_SEC_NEXT; extern int XP_SEC_BACK; extern int XP_SEC_FINISHED; extern int XP_SEC_MOREINFO; extern int XP_SEC_CONFIG; extern int XP_SEC_SHOWCERT; extern int XP_SEC_SHOWORDER; extern int XP_SEC_SHOWDOCINFO; extern int XP_SEC_NEXT_KLUDGE; extern int XP_SEC_BACK_KLUDGE; extern int XP_SEC_RENEW; extern int XP_SEC_NEW; extern int XP_SEC_RELOAD; extern int XP_SEC_DELETE; extern int XP_SEC_EDIT; extern int XP_SEC_LOGIN; extern int XP_SEC_LOGOUT; extern int XP_SEC_SETPASSWORD; extern int XP_SEC_SAVEAS; extern int XP_SEC_FETCH; extern int XP_SEC_GRANT; extern int XP_SEC_DENY; extern int XP_SEC_DETAILS; extern int XP_SEC_CERTIFICATE; extern int XP_DIALOG_CANCEL_BUTTON_STRINGS; extern int XP_DIALOG_CANCEL_CONTINUE_BUTTON_STRINGS; extern int XP_DIALOG_CANCEL_OK_BUTTON_STRINGS; extern int XP_DIALOG_CANCEL_OK_MOREINFO_BUTTON_STRINGS; extern int XP_DIALOG_FETCH_CANCEL_BUTTON_STRINGS; extern int XP_DIALOG_CONTINUE_BUTTON_STRINGS; extern int XP_DIALOG_FOOTER_STRINGS; extern int XP_DIALOG_HEADER_STRINGS; extern int XP_DIALOG_MIDDLE_STRINGS; extern int XP_DIALOG_NULL_STRINGS; extern int XP_DIALOG_OK_BUTTON_STRINGS; extern int XP_EMPTY_STRINGS; extern int XP_PANEL_FIRST_BUTTON_STRINGS; extern int XP_PANEL_FOOTER_STRINGS; extern int XP_PANEL_HEADER_STRINGS; extern int XP_PANEL_LAST_BUTTON_STRINGS; extern int XP_PANEL_MIDDLE_BUTTON_STRINGS; extern int XP_PANEL_ONLY_BUTTON_STRINGS; extern int XP_ALERT_TITLE_STRING; extern int XP_DIALOG_JS_HEADER_STRINGS; extern int XP_DIALOG_JS_HEADER_STRINGS_WITH_UTF8_CHARSET; extern int XP_DIALOG_JS_MIDDLE_STRINGS; extern int XP_DIALOG_JS_FOOTER_STRINGS; extern int XP_BANNER_FONTFACE_INFO_STRING; extern int XP_DIALOG_STYLEINFO_STRING; typedef struct { PRCList link; char *data; unsigned int len; } bufferNode; typedef struct _htmlDialogStream { PRCList queuedBuffers; PRArenaPool *arena; NET_StreamClass *stream; URL_Struct *url; PRBool buffering; char *curbuf; unsigned int curlen; } HTMLDialogStream; typedef struct { void *window; void (* deleteWinCallback)(void *arg); void *arg; PRArenaPool *freeArena; } deleteWindowCBArg; static void deleteWindow(void *closure) { deleteWindowCBArg *state; state = (deleteWindowCBArg *)closure; FE_DestroyWindow((MWContext *)state->window); if ( state->deleteWinCallback ) { (* state->deleteWinCallback)(state->arg); } if ( state->freeArena != NULL ) { PORT_FreeArena(state->freeArena, PR_FALSE); } PORT_Free(state); return; } static SECStatus writeOrBuffer(HTMLDialogStream *stream) { unsigned int cnt; char *tmpdest; bufferNode *node; int ret; if ( ! stream->buffering ) { cnt = (*(stream->stream)->is_write_ready) (stream->stream); /* if stream is clogged, then start buffering */ if ( cnt < stream->curlen ) { /* we need to copy the current contents of the reusable * buffer to a persistent buffer allocated from the * arena, then free the persistent buffer */ tmpdest = (char *)PORT_ArenaAlloc(stream->arena, stream->curlen); if ( tmpdest == NULL ) { goto loser; } PORT_Memcpy(tmpdest, stream->curbuf, stream->curlen); PORT_Free(stream->curbuf); stream->curbuf = tmpdest; stream->buffering = PR_TRUE; } } if ( stream->buffering ) { node = PORT_ArenaAlloc(stream->arena, sizeof(bufferNode)); if ( node == NULL ) { goto loser; } PR_APPEND_LINK(&node->link, &stream->queuedBuffers); node->data = stream->curbuf; node->len = stream->curlen; } else { ret = (*(stream->stream)->put_block) (stream->stream, stream->curbuf, stream->curlen); if ( ret < 0 ) { goto loser; } } return(SECSuccess); loser: return(SECFailure); } static SECStatus putStringToStream(HTMLDialogStream *stream, char *string, PRBool quote) { SECStatus rv; char *tmpptr; char *destptr; int curcount; unsigned int maxsize; if (*string == 0) { return(SECSuccess); } if ( stream->buffering ) { /* pick a size that is convenient based on the current behaviour * of the html parser */ maxsize = 2000; /* XXX - we know what the parser does here!! */ stream->curbuf = destptr = (char *)PORT_ArenaAlloc(stream->arena, maxsize); } else { maxsize = (*(stream->stream)->is_write_ready) (stream->stream); if ( maxsize == 0 ) { /* we are switching to buffering now */ maxsize = 2000; stream->curbuf = destptr = (char *)PORT_ArenaAlloc(stream->arena, maxsize); stream->buffering = PR_TRUE; } else { stream->curbuf = destptr = (char *)PORT_Alloc( maxsize ); } } if ( stream->curbuf == NULL ) { return(SECFailure); } curcount = 0; tmpptr = string; if ( quote ) { while ( *tmpptr ) { if ( *tmpptr == '\'' ) { *destptr = '\\'; destptr++; *destptr = *tmpptr; destptr++; curcount += 2; } else if ( *tmpptr == '\\' ) { *destptr = '\\'; destptr++; *destptr = '\\'; destptr++; curcount += 2; } else if ( *tmpptr == '\n' ) { *destptr = '\\'; destptr++; *destptr = 'n'; destptr++; curcount += 2; } else if ( *tmpptr == '\r' ) { *destptr = '\\'; destptr++; *destptr = 'r'; destptr++; curcount += 2; } else if ( *tmpptr == '/' ) { *destptr = '\\'; destptr++; *destptr = '/'; destptr++; curcount += 2; } else { *destptr = *tmpptr; destptr++; curcount++; } tmpptr++; if ( curcount >= ( maxsize - 1 ) ) { stream->curlen = curcount; rv = writeOrBuffer(stream); if ( rv != SECSuccess ) { goto loser; } if ( stream->buffering && ( *tmpptr != '\0' ) ) { maxsize = 2000; /*XXX-we know what the parser does here!!*/ stream->curbuf = destptr = (char *)PORT_ArenaAlloc(stream->arena, maxsize); if ( stream->curbuf == NULL ) { goto loser; } } else { destptr = stream->curbuf; } curcount = 0; } } } else { while ( *tmpptr ) { *destptr = *tmpptr; destptr++; curcount++; tmpptr++; if ( curcount >= ( maxsize - 1 ) ) { stream->curlen = curcount; rv = writeOrBuffer(stream); if ( rv != SECSuccess ) { goto loser; } if ( stream->buffering && ( *tmpptr != '\0') ) { maxsize = 2000; /*XXX-we know what the parser does here!!*/ stream->curbuf = destptr = (char *)PORT_ArenaAlloc(stream->arena, maxsize); if ( stream->curbuf == NULL ) { goto loser; } } else { destptr = stream->curbuf; } curcount = 0; } } } if ( curcount > 0 ) { stream->curlen = curcount; rv = writeOrBuffer(stream); if ( rv != SECSuccess ) { goto loser; } } rv = SECSuccess; goto done; loser: rv = SECFailure; done: if ( ( !stream->buffering ) && ( stream->curbuf != NULL ) ) { PORT_Free(stream->curbuf); } return(rv); } SECStatus XP_PutDialogStringsToStream(HTMLDialogStream *stream, XPDialogStrings *strs, PRBool quote) { SECStatus rv; char *src, *token, *junk; int argnum; void *proto_win = stream->stream->window_id; src = strs->contents; while ((token = PORT_Strchr(src, '%'))) { *token = 0; rv = putStringToStream(stream, src, quote); if (rv) { return(SECFailure); } *token = '%'; /* non-destructive... */ token++; /* now points to start of token */ src = PORT_Strchr(token, '%'); *src = 0; argnum = (int)XP_STRTOUL(token, &junk, 10); if (junk != token) { /* A number */ PORT_Assert(argnum <= strs->nargs); if (strs->args[argnum]) { rv = putStringToStream(stream, strs->args[argnum], quote); if (rv) { return(SECFailure); } } } else if (!PORT_Strcmp(token, "-cont-")) /* continuation */ /* Do Nothing */; else if (*token == 0) { /* %% -> % */ rv = putStringToStream(stream, "%", quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "cancel")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_CANCEL), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "ok")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_OK), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "continue")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_CONTINUE), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "next")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_NEXT), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "back")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_BACK), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "finished")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_FINISHED), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "moreinfo")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_MOREINFO), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "config")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_CONFIG), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "showcert")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_SHOWCERT), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "showorder")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_SHOWORDER), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "showdocinfo")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_SHOWDOCINFO), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "renew")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_RENEW), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "new")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_NEW), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "reload")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_RELOAD), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "delete")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_DELETE), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "edit")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_EDIT), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "login")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_LOGIN), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "logout")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_LOGOUT), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "setpassword")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_SETPASSWORD), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "fetch")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_FETCH), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "banner-sec")) { rv = putStringToStream(stream, "

", quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "saveas")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_SAVEAS), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "-styleinfo-")) { rv = putStringToStream(stream, XP_GetString(XP_DIALOG_STYLEINFO_STRING), quote); if(rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "sec-banner-begin")) { rv = putStringToStream(stream, "" "
" "", quote); if (rv) { return(SECFailure); } rv = putStringToStream(stream, XP_GetString(XP_BANNER_FONTFACE_INFO_STRING), quote); if (rv) { return(SECFailure); } rv = putStringToStream(stream, "", quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "sec-banner-end")) { rv = putStringToStream(stream, "

", quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "grant")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_GRANT), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "deny")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_DENY), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "details")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_DETAILS), quote); if (rv) { return(SECFailure); } } else if (!PORT_Strcmp(token, "certificate")) { rv = putStringToStream(stream, XP_GetString(XP_SEC_CERTIFICATE), quote); if (rv) { return(SECFailure); } } else { PORT_Assert(0); /* Failure: Unhandled token. */ } *src = '%'; /* non-destructive... */ src++; /* now points past %..% */ } rv = putStringToStream(stream, src, quote); if (rv) { return(SECFailure); } return(SECSuccess); } SECStatus XP_PutDialogStringsTagToStream(HTMLDialogStream *stream, int num, PRBool quote) { SECStatus rv; XPDialogStrings *strings; strings = XP_GetDialogStrings(num); if ( strings == NULL ) { return(SECFailure); } rv = XP_PutDialogStringsToStream(stream, strings, quote); XP_FreeDialogStrings(strings); return(rv); } char ** cgi_ConvertStringToArgVec(char *str, int length, int *argcp) { char *cp, **avp; int argc; char c; char tmp; char *destp; char **av = 0; if (!str) { if (argcp) *argcp = 0; return 0; } cp = str + length - 1; while ( (*cp == '\n') || (*cp == '\r') ) { *cp-- = '\0'; } /* 1. Count number of args in input */ argc = 1; cp = str; for (;;) { cp = PORT_Strchr(cp, '='); if (!cp) break; cp++; argc++; cp = PORT_Strchr(cp, '&'); if (!cp) break; cp++; argc++; } /* 2. Allocate space for argvec array and copy of strings */ *argcp = argc; av = (char**) PORT_ZAlloc(((argc + 1) * sizeof(char*)) + strlen(str) + 1); destp = ((char *)av) + ( (argc + 1) * sizeof(char *) ); if (!av) goto loser; /* ** 3. Break up input into each arg chunk. Once we break an entry up, ** compress it in place, replacing the magic characters with their ** correct value. */ avp = av; cp = str; *avp++ = destp; while( ( c = (*cp++) ) != '\0' ) { switch( c ) { case '&': case '=': *destp++ = '\0'; *avp++ = destp; break; case '+': *destp++ = ' '; break; case '%': c = *cp++; if ((c >= 'a') && (c <= 'f')) { tmp = c - 'a' + 10; } else if ((c >= 'A') && (c <= 'F')) { tmp = c - 'A' + 10; } else { tmp = c - '0'; } tmp = tmp << 4; c = *cp++; if ((c >= 'a') && (c <= 'f')) { tmp |= ( c - 'a' + 10 ); } else if ((c >= 'A') && (c <= 'F')) { tmp |= ( c - 'A' + 10 ); } else { tmp |= ( c - '0' ); } *destp++ = tmp; break; default: *destp++ = c; break; } *destp = '\0'; } return av; loser: PORT_Free(av); return 0; } /* * return the value of a name value pair */ char * XP_FindValueInArgs(const char *name, char **av, int ac) { for( ;ac > 0; ac -= 2, av += 2 ) { if ( PORT_Strcmp(name, av[0]) == 0 ) { return(av[1]); } } return(0); } void XP_HandleHTMLDialog(URL_Struct *url) { char **av = NULL; int ac; char *handleString; char *buttonString; XPDialogState *handle = NULL; unsigned int button; PRBool ret; /* collect post data */ av = cgi_ConvertStringToArgVec(url->post_data, url->post_data_size, &ac); if ( av == NULL ) { goto loser; } /* get the handle */ handleString = XP_FindValueInArgs("handle", av, ac); if ( handleString == NULL ) { goto loser; } /* get the button value */ buttonString = XP_FindValueInArgs("button", av, ac); if ( buttonString == NULL ) { goto loser; } handle = NULL; #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */ sscanf(handleString, "%lu", &handle); #else sscanf(handleString, "%p", &handle); #endif if ( handle == NULL ) { goto loser; } if ( handle->deleted ) { goto loser; } if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_OK)) == 0 ) { button = XP_DIALOG_OK_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_CANCEL)) == 0 ) { button = XP_DIALOG_CANCEL_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_CONTINUE)) == 0 ) { button = XP_DIALOG_CONTINUE_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_MOREINFO)) == 0 ) { button = XP_DIALOG_MOREINFO_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_FETCH)) == 0 ) { button = XP_DIALOG_FETCH_BUTTON; } else { button = 0; } /* call the application handler */ ret = PR_FALSE; if ( handle->dialogInfo->handler != NULL ) { ret = (* handle->dialogInfo->handler)(handle, av, ac, button); } loser: /* free arg vector */ if ( av != NULL ) { PORT_Free(av); } if ( ( handle != NULL ) && ( ret == PR_FALSE ) && ( !handle->deleted ) ) { deleteWindowCBArg *delstate; /* set callback to destroy the window */ delstate = (deleteWindowCBArg *)PORT_Alloc(sizeof(deleteWindowCBArg)); if ( delstate ) { delstate->window = (void *)handle->window; delstate->arg = handle->cbarg; delstate->deleteWinCallback = handle->deleteCallback; delstate->freeArena = handle->arena; (void)FE_SetTimeout(deleteWindow, (void *)delstate, 0); } handle->deleted = PR_TRUE; } return; } void xp_InitChrome(void *proto_win, Chrome *chrome, int width, int height, PRBool isModal) { PORT_Memset(chrome, 0, sizeof(Chrome)); chrome->type = MWContextDialog; chrome->w_hint = width; chrome->h_hint = height; chrome->is_modal = TRUE; /* Try to make the dialog fit on the screen, centered over the proto_win */ if ( proto_win && chrome->w_hint && chrome->h_hint ) { int32 screenWidth = 0; int32 screenHeight = 0; Chrome protoChrome; PORT_Memset(&protoChrome, 0, sizeof(protoChrome)); /* We want to shrink the dialog to fit on the screen if necessary. * * The inner dimensions of the dialog have to be specified in the * Chrome. However, we want to OUTER dimensions to fit on the screen. * We don't know the difference between the inner and outer dimensions. * We could try to find that difference information from the * proto_win's Chrome structure, but the proto_win probably has * a completely different structure from our dialog windows. So we * just guess... */ FE_GetScreenSize ((MWContext *) proto_win, &screenWidth, &screenHeight); if ( screenWidth && screenHeight ) { /* arbitrary slop around dialog */ if (chrome->w_hint > screenWidth - 20) chrome->w_hint = screenWidth - 20; if (chrome->h_hint > screenHeight - 30) chrome->h_hint = screenHeight - 30; } /* Now, try to find out where the proto_win is so we can center on it. */ FE_QueryChrome((MWContext *)proto_win, &protoChrome); /* Did we get anything useful? */ if ( protoChrome.location_is_chrome && protoChrome.w_hint && protoChrome.h_hint ) { chrome->location_is_chrome = TRUE; chrome->l_hint = protoChrome.l_hint + (protoChrome.w_hint - chrome->w_hint) / 2; chrome->t_hint = protoChrome.t_hint + (protoChrome.h_hint - chrome->h_hint) / 2; } /* If we moved the dialog, make sure we didn't move it off the screen. */ if ( chrome->location_is_chrome && screenWidth && screenHeight ) { if ( chrome->l_hint < 0) { chrome->l_hint = 0; } if ( chrome->t_hint < 0) { chrome->t_hint = 0; } if ( chrome->l_hint > ( screenWidth - chrome->w_hint ) ) { chrome->l_hint = screenWidth - chrome->w_hint; } if ( chrome->t_hint > ( screenHeight - chrome->h_hint ) ) { chrome->t_hint = screenHeight - chrome->h_hint; } } } return; } XPDialogState * XP_MakeHTMLDialog(void *proto_win, XPDialogInfo *dialogInfo, int titlenum, XPDialogStrings *strings, void *arg, PRBool utf8CharSet) { Chrome chrome; xp_InitChrome(proto_win, &chrome, dialogInfo->width, dialogInfo->height, PR_TRUE); return(XP_MakeHTMLDialogWithChrome(proto_win, dialogInfo, titlenum, strings, &chrome, arg, utf8CharSet)); } void freeHTMLDialogStream(HTMLDialogStream *stream) { if ( stream != NULL ) { if ( stream->stream != NULL ) { PORT_Free(stream->stream); } if ( stream->url != NULL ) { NET_FreeURLStruct(stream->url); } if ( stream->arena != NULL ) { PORT_FreeArena(stream->arena, PR_FALSE); } } return; } HTMLDialogStream * newHTMLDialogStream(void *cx) { HTMLDialogStream *stream; PRArenaPool *arena; arena = PORT_NewArena(512); if ( arena == NULL ) { goto loser; } /* make an html dialog stream */ stream = (HTMLDialogStream *)PORT_ArenaZAlloc(arena, sizeof(HTMLDialogStream)); if ( stream == NULL ) { goto loser; } stream->arena = arena; /* initialize the list of queued buffers */ PR_INIT_CLIST(&stream->queuedBuffers); /* create a URL struct */ stream->url = NET_CreateURLStruct("", NET_DONT_RELOAD); if ( stream->url == NULL ) { goto loser; } StrAllocCopy(stream->url->content_type, TEXT_HTML); /* make a netlib stream to display in the window */ stream->stream = NET_StreamBuilder(FO_PRESENT, stream->url, cx); if ( stream->stream == NULL ) { goto loser; } return(stream); loser: freeHTMLDialogStream(stream); return(NULL); } void emptyQueues(void *arg) { HTMLDialogStream *stream; bufferNode *node; unsigned int cnt; int ret; stream = (HTMLDialogStream *)arg; while ( ! PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) { /* get the head node */ node = (bufferNode *)PR_LIST_HEAD(&stream->queuedBuffers); cnt = (*(stream->stream)->is_write_ready)(stream->stream); if ( cnt < node->len ) { /* layout hasn't unclogged yet */ break; } ret = (*(stream->stream)->put_block)(stream->stream, node->data, node->len); if ( ret < 0 ) { goto loser; } /* remove it from the list */ PR_REMOVE_LINK(&node->link); } if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) { (*stream->stream->complete) (stream->stream); freeHTMLDialogStream(stream); } else { FE_SetTimeout(emptyQueues, (void *)stream, 100); } return; loser: freeHTMLDialogStream(stream); return; } void * xp_MakeHTMLDialogWindow(void *proto_win, Chrome *chrome) { MWContext *cx; /* make the window */ cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, chrome); if ( cx == NULL ) { goto done; } #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else LM_ForceJSEnabled(cx); #endif /* MOZ_NGLAYOUT */ /* XXX - get rid of session history */ SHIST_EndSession(cx); PORT_Memset((void *)&cx->hist, 0, sizeof(cx->hist)); done: return(cx); } SECStatus xp_DrawHTMLDialog(void *cx, XPDialogInfo *dialogInfo, int titlenum, XPDialogStrings *strings, void *state, PRBool utf8CharSet) { HTMLDialogStream *stream = NULL; SECStatus rv; char buf[50]; XPDialogStrings *dlgstrings; int buttontag; /* make the stream */ stream = newHTMLDialogStream(cx); if ( stream == NULL ) { goto loser; } if ( utf8CharSet ) { dlgstrings = XP_GetDialogStrings(XP_DIALOG_JS_HEADER_STRINGS_WITH_UTF8_CHARSET); } else { dlgstrings = XP_GetDialogStrings(XP_DIALOG_JS_HEADER_STRINGS); } if ( dlgstrings == NULL ) { goto loser; } /* put the title in header */ XP_CopyDialogString(dlgstrings, 0, XP_GetString(titlenum)); /* send html header stuff */ rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_FALSE); XP_FreeDialogStrings(dlgstrings); if ( rv != SECSuccess ) { goto loser; } dlgstrings = XP_GetDialogStrings(XP_DIALOG_HEADER_STRINGS); if ( dlgstrings == NULL ) { goto loser; } /* put handle in header */ #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */ sprintf(buf, "%lu", state); #else sprintf(buf, "%p", state); #endif XP_SetDialogString(dlgstrings, 0, buf); /* send html header stuff */ rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_TRUE); XP_FreeDialogStrings(dlgstrings); if ( rv != SECSuccess ) { goto loser; } /* send caller's message */ rv = XP_PutDialogStringsToStream(stream, strings, PR_TRUE); if ( rv != SECSuccess ) { goto loser; } /* send trailing info */ rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_FOOTER_STRINGS, PR_TRUE); if ( rv != SECSuccess ) { goto loser; } /* send button strings */ switch(dialogInfo->buttonFlags) { case XP_DIALOG_CANCEL_BUTTON: buttontag = XP_DIALOG_CANCEL_BUTTON_STRINGS; break; case XP_DIALOG_CONTINUE_BUTTON: buttontag = XP_DIALOG_CONTINUE_BUTTON_STRINGS; break; case XP_DIALOG_OK_BUTTON: buttontag = XP_DIALOG_OK_BUTTON_STRINGS; break; case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_OK_BUTTON: buttontag = XP_DIALOG_CANCEL_OK_BUTTON_STRINGS; break; case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_CONTINUE_BUTTON: buttontag = XP_DIALOG_CANCEL_CONTINUE_BUTTON_STRINGS; break; case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_OK_BUTTON | XP_DIALOG_MOREINFO_BUTTON: buttontag = XP_DIALOG_CANCEL_OK_MOREINFO_BUTTON_STRINGS; break; case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_FETCH_BUTTON: buttontag = XP_DIALOG_FETCH_CANCEL_BUTTON_STRINGS; break; default: buttontag = XP_DIALOG_NULL_STRINGS; break; } rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_MIDDLE_STRINGS, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } rv = XP_PutDialogStringsTagToStream(stream, buttontag, PR_TRUE); if ( rv != SECSuccess ) { goto loser; } rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_FOOTER_STRINGS, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) { /* complete the stream */ (*stream->stream->complete) (stream->stream); freeHTMLDialogStream(stream); return(SECSuccess); } else { FE_SetTimeout(emptyQueues, (void *)stream, 0); return(SECSuccess); } loser: /* XXX free URL and CX ???*/ /* abort the stream */ if ( stream != NULL ) { if ( stream->stream != NULL ) { (*stream->stream->abort)(stream->stream, rv); } } freeHTMLDialogStream(stream); return(SECFailure); } XPDialogState * XP_MakeHTMLDialogWithChrome(void *proto_win, XPDialogInfo *dialogInfo, int titlenum, XPDialogStrings *strings, Chrome *chrome, void *arg, PRBool utf8CharSet) { void *cx; SECStatus rv; XPDialogState *state; PRArenaPool *arena = NULL; arena = PORT_NewArena(1024); if ( arena == NULL ) { return(NULL); } /* allocate the state structure */ state = (XPDialogState *)PORT_ArenaAlloc(arena, sizeof(XPDialogState)); if ( state == NULL ) { goto loser; } state->deleted = PR_FALSE; state->arena = arena; state->dialogInfo = dialogInfo; state->arg = arg; state->deleteCallback = NULL; state->cbarg = NULL; state->proto_win = proto_win; state->window = xp_MakeHTMLDialogWindow(proto_win, chrome); if ( state->window == NULL ) { goto loser; } rv = xp_DrawHTMLDialog(state->window, dialogInfo, titlenum, strings, (void *)state, utf8CharSet); if ( rv != SECSuccess ) { goto loser; } return(state); loser: PORT_FreeArena(arena, PR_FALSE); return(NULL); } void * xp_MakeHTMLDialogPass1(void *proto_win, XPDialogInfo *dialogInfo) { Chrome chrome; xp_InitChrome(proto_win, &chrome, dialogInfo->width, dialogInfo->height, PR_TRUE); return(xp_MakeHTMLDialogWindow(proto_win, &chrome)); } XPDialogState * xp_MakeHTMLDialogPass2(void *proto_win, void *cx, XPDialogInfo *dialogInfo, int titlenum, XPDialogStrings *strings, void *arg, PRBool utf8CharSet) { SECStatus rv; XPDialogState *state; PRArenaPool *arena = NULL; arena = PORT_NewArena(1024); if ( arena == NULL ) { return(NULL); } /* allocate the state structure */ state = (XPDialogState *)PORT_ArenaAlloc(arena, sizeof(XPDialogState)); if ( state == NULL ) { goto loser; } state->deleted = PR_FALSE; state->arena = arena; state->dialogInfo = dialogInfo; state->arg = arg; state->deleteCallback = NULL; state->cbarg = NULL; state->proto_win = proto_win; state->window = cx; rv = xp_DrawHTMLDialog(state->window, dialogInfo, titlenum, strings, (void *)state, utf8CharSet); if ( rv != SECSuccess ) { goto loser; } return(state); loser: PORT_FreeArena(arena, PR_FALSE); return(NULL); } int XP_RedrawRawHTMLDialog(XPDialogState *state, XPDialogStrings *strings, int handlestring) { HTMLDialogStream *stream = NULL; SECStatus rv; char buf[50]; stream = newHTMLDialogStream(state->window); if ( stream == NULL ) { goto loser; } /* put handle in header */ #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */ sprintf(buf, "%lu", state); #else sprintf(buf, "%p", state); #endif XP_SetDialogString(strings, handlestring, buf); /* send caller's message */ rv = XP_PutDialogStringsToStream(stream, strings, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } /* complete the stream */ if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) { /* complete the stream */ (*stream->stream->complete) (stream->stream); freeHTMLDialogStream(stream); return((int)SECSuccess); } else { FE_SetTimeout(emptyQueues, (void *)stream, 0); return((int)SECSuccess); } loser: /* XXX free URL and CX ???*/ /* abort the stream */ if ( stream != NULL ) { if ( stream->stream != NULL ) { (*stream->stream->abort)(stream->stream, rv); } } freeHTMLDialogStream(stream); return((int)SECFailure); } /* ***** What a hack!!! Make the security advisor modeless on the Mac. ***** */ #ifdef XP_MAC extern int XP_SECURITY_ADVISOR_TITLE_STRING; #endif XPDialogState * XP_MakeRawHTMLDialog(void *proto_win, XPDialogInfo *dialogInfo, int titlenum, XPDialogStrings *strings, int handlestring, void *arg) { MWContext *cx = NULL; SECStatus rv; XPDialogState *state; PRArenaPool *arena = NULL; Chrome chrome; PORT_Memset(&chrome, 0, sizeof(chrome)); chrome.type = MWContextDialog; chrome.w_hint = dialogInfo->width; chrome.h_hint = dialogInfo->height; /* ***** What a hack!!! Make the security advisor modeless on the Mac. ***** */ #ifdef XP_MAC chrome.is_modal = (titlenum == XP_SECURITY_ADVISOR_TITLE_STRING) ? FALSE : TRUE; #else chrome.is_modal = TRUE; #endif arena = PORT_NewArena(1024); if ( arena == NULL ) { return(NULL); } /* allocate the state structure */ state = (XPDialogState *)PORT_ArenaAlloc(arena, sizeof(XPDialogState)); if ( state == NULL ) { goto loser; } state->deleted = PR_FALSE; state->arena = arena; state->dialogInfo = dialogInfo; state->arg = arg; state->deleteCallback = NULL; state->cbarg = NULL; /* make the window */ /* ***** What a hack!!! Make the security advisor modeless on the Mac. ***** */ #ifdef XP_MAC if (titlenum == XP_SECURITY_ADVISOR_TITLE_STRING) cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, XP_GetString(titlenum), &chrome); else #else cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, &chrome); #endif if ( cx == NULL ) { goto loser; } #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else LM_ForceJSEnabled(cx); #endif /* MOZ_NGLAYOUT */ state->window = (void *)cx; state->proto_win = proto_win; /* XXX - get rid of session history */ SHIST_EndSession(cx); PORT_Memset((void *)&cx->hist, 0, sizeof(cx->hist)); rv = (SECStatus)XP_RedrawRawHTMLDialog(state, strings, handlestring); if ( rv != SECSuccess ) { goto loser; } return(state); loser: /* free the arena */ if ( arena != NULL ) { PORT_FreeArena(arena, PR_FALSE); } return(NULL); } static void displayPanelCB(void *arg) { XPPanelState *state; HTMLDialogStream *stream; XPDialogStrings *contentstrings; SECStatus rv; char buf[50]; XPDialogStrings *dlgstrings; int buttontag; state = (XPPanelState *)arg; stream = newHTMLDialogStream(state->window); if (stream == NULL) { goto loser; } dlgstrings = XP_GetDialogStrings(XP_DIALOG_JS_HEADER_STRINGS); if ( dlgstrings == NULL ) { goto loser; } /* put the title in header */ XP_CopyDialogString(dlgstrings, 0, XP_GetString(state->titlenum)); /* send html header stuff */ rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_FALSE); XP_FreeDialogStrings(dlgstrings); if ( rv != SECSuccess ) { goto loser; } /* get header strings */ dlgstrings = XP_GetDialogStrings(XP_PANEL_HEADER_STRINGS); if ( dlgstrings == NULL ) { goto loser; } /* put handle in header */ #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */ sprintf(buf, "%lu", state); #else sprintf(buf, "%p", state); #endif XP_SetDialogString(dlgstrings, 0, buf); /* send html header stuff */ rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_TRUE); /* free the strings */ XP_FreeDialogStrings(dlgstrings); if ( rv != SECSuccess ) { goto loser; } /* send panel message */ contentstrings = (* state->panels[state->curPanel].content)(state); if ( contentstrings == NULL ) { goto loser; } state->curStrings = contentstrings; rv = XP_PutDialogStringsToStream(stream, contentstrings, PR_TRUE); if ( rv != SECSuccess ) { goto loser; } XP_FreeDialogStrings(contentstrings); /* send html middle stuff */ rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_FOOTER_STRINGS, PR_TRUE); if ( rv != SECSuccess ) { goto loser; } if ( state->panels[state->curPanel].flags & XP_PANEL_FLAG_ONLY ) { /* if its the only panel */ buttontag = XP_PANEL_ONLY_BUTTON_STRINGS; } else if ( ( state->curPanel == ( state->panelCount - 1 ) ) || ( state->panels[state->curPanel].flags & XP_PANEL_FLAG_FINAL ) ) { /* if its the last panel or has the final flag set */ buttontag = XP_PANEL_LAST_BUTTON_STRINGS; } else if ( ( state->curPanel == 0 ) || ( state->panels[state->curPanel].flags & XP_PANEL_FLAG_FIRST ) ) { buttontag = XP_PANEL_FIRST_BUTTON_STRINGS; } else { buttontag = XP_PANEL_MIDDLE_BUTTON_STRINGS; } rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_MIDDLE_STRINGS, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } /* send button strings */ rv = XP_PutDialogStringsTagToStream(stream, buttontag, PR_TRUE); if ( rv != SECSuccess ) { goto loser; } rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_FOOTER_STRINGS, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } /* complete the stream */ if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) { /* complete the stream */ (*stream->stream->complete) (stream->stream); freeHTMLDialogStream(stream); return; } else { FE_SetTimeout(emptyQueues, (void *)stream, 0); return; } return; loser: /* abort the stream */ if ( stream != NULL ) { if ( stream->stream != NULL ) { (*stream->stream->abort)(stream->stream, rv); } } freeHTMLDialogStream(stream); return; } static void displayPanel(XPPanelState *state) { (void)FE_SetTimeout(displayPanelCB, (void *)state, 0); } void XP_MakeHTMLPanel(void *proto_win, XPPanelInfo *panelInfo, int titlenum, void *arg) { PRArenaPool *arena; XPPanelState *state = NULL; Chrome chrome; MWContext *cx; arena = PORT_NewArena(1024); if ( arena == NULL ) { return; } state = (XPPanelState *)PORT_ArenaAlloc(arena, sizeof(XPPanelState)); if ( state == NULL ) { return; } state->deleted = PR_FALSE; state->arena = arena; state->panels = panelInfo->desc; state->panelCount = panelInfo->panelCount; state->curPanel = 0; state->arg = arg; state->finish = panelInfo->finishfunc; state->info = panelInfo; state->titlenum = titlenum; state->deleteCallback = NULL; state->cbarg = NULL; /* make the window */ PORT_Memset(&chrome, 0, sizeof(chrome)); chrome.type = MWContextDialog; chrome.w_hint = panelInfo->width; chrome.h_hint = panelInfo->height; chrome.is_modal = TRUE; cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, &chrome); state->window = (void *)cx; if ( state->window == NULL ) { PORT_FreeArena(arena, PR_FALSE); return; } #ifdef MOZ_NGLAYOUT XP_ASSERT(0); #else LM_ForceJSEnabled(cx); #endif /* MOZ_NGLAYOUT */ /* XXX - get rid of session history */ SHIST_EndSession(cx); PORT_Memset((void *)&cx->hist, 0, sizeof(cx->hist)); /* display the first panel */ displayPanel(state); return; } void XP_HandleHTMLPanel(URL_Struct *url) { char **av = NULL; int ac; char *handleString; char *buttonString; XPPanelState *state = NULL; unsigned int button; int nextpanel; /* collect post data */ av = cgi_ConvertStringToArgVec(url->post_data, url->post_data_size, &ac); if ( av == NULL ) { goto loser; } /* get the handle */ handleString = XP_FindValueInArgs("handle", av, ac); if ( handleString == NULL ) { goto loser; } /* get the button value */ buttonString = XP_FindValueInArgs("button", av, ac); if ( buttonString == NULL ) { goto loser; } /* extract a handle pointer from the string */ state = NULL; #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */ sscanf(handleString, "%lu", &state); #else sscanf(handleString, "%p", &state); #endif if ( state == NULL ) { goto loser; } if ( state->deleted ) { goto loser; } /* figure out which button was pressed */ if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_NEXT_KLUDGE)) == 0 ) { button = XP_DIALOG_NEXT_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_CANCEL)) == 0 ) { button = XP_DIALOG_CANCEL_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_BACK_KLUDGE)) == 0 ) { button = XP_DIALOG_BACK_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_FINISHED)) == 0 ) { button = XP_DIALOG_FINISHED_BUTTON; } else if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_MOREINFO)) == 0 ) { button = XP_DIALOG_MOREINFO_BUTTON; } else { button = 0; } /* call the application handler */ if ( state->panels[state->curPanel].handler != NULL ) { nextpanel = (* state->panels[state->curPanel].handler)(state, av, ac, button); } else { nextpanel = 0; } if ( button == XP_DIALOG_CANCEL_BUTTON ) { if ( state->finish ) { (* state->finish)(state, PR_TRUE); } goto done; } if ( nextpanel != 0 ) { state->curPanel = nextpanel - 1; } else { switch ( button ) { case XP_DIALOG_BACK_BUTTON: PORT_Assert(state->curPanel > 0); state->curPanel = state->curPanel - 1; break; case XP_DIALOG_NEXT_BUTTON: PORT_Assert(state->curPanel < ( state->panelCount - 1 ) ); state->curPanel = state->curPanel + 1; break; case XP_DIALOG_FINISHED_BUTTON: if ( state->finish ) { (* state->finish)(state, PR_FALSE); } goto done; } } displayPanel(state); /* free arg vector */ PORT_Free(av); return; loser: done: /* free arg vector */ if ( av != NULL ) { PORT_Free(av); } if ( ( state != NULL ) && ( !state->deleted ) ) { /* destroy the window */ deleteWindowCBArg *delstate; /* set callback to destroy the window */ delstate = (deleteWindowCBArg *)PORT_Alloc(sizeof(deleteWindowCBArg)); if ( delstate ) { delstate->window = (void *)state->window; delstate->arg = state->cbarg; delstate->deleteWinCallback = state->deleteCallback; delstate->freeArena = state->arena; (void)FE_SetTimeout(deleteWindow, (void *)delstate, 0); } state->deleted = PR_TRUE; } return; } /* * fetch a string from the dialog strings database */ XPDialogStrings * XP_GetDialogStrings(int stringnum) { XPDialogStrings *header = NULL; PRArenaPool *arena = NULL; char *dst, *src; int n, size, len, done = 0; /* get a new arena */ arena = PORT_NewArena(XP_STRINGS_CHUNKSIZE); if ( arena == NULL ) { return(NULL); } /* allocate the header structure */ header = (XPDialogStrings *)PORT_ArenaAlloc(arena, sizeof(XPDialogStrings)); if ( header == NULL ) { goto loser; } /* init the header */ header->arena = arena; header->basestringnum = stringnum; src = XP_GetString(stringnum); len = PORT_Strlen(src); size = len + 1; dst = header->contents = (char *)PORT_ArenaAlloc(arena, sizeof(char) * size); if (dst == NULL) goto loser; while (!done) { /* Concatenate pieces to form message */ PORT_Memcpy(dst, src, len+1); done = 1; if (XP_STRSTR(src, "%-cont-%")) { /* Continuation */ src = XP_GetString(++stringnum); len = PORT_Strlen(src); header->contents = (char *)PORT_ArenaGrow(arena, header->contents, size, size + len); if (header->contents == NULL) goto loser; dst = header->contents + size - 1; size += len; done = 0; } } /* At this point we should have the complete message in header->contents, including like %-cont-%, which will be ignored later. */ /* Count the arguments in the message */ header->nargs = -1; /* Support %0% as lowest token */ src = header->contents; while ((src = PORT_Strchr(src, '%'))) { src++; n = (int)XP_STRTOUL(src, &dst, 10); if (dst == src) { /* Integer not found... */ src = PORT_Strchr(src, '%') + 1; /* so skip this %..% */ PORT_Assert(NULL != src-1); /* Unclosed %..% ? */ continue; } if (header->nargs < n) header->nargs = n; src = dst + 1; } if (++(header->nargs) > 0) /* Allocate space for arguments */ header->args = (char **)PORT_ArenaZAlloc(arena, sizeof(char *) * header->nargs); return(header); loser: PORT_FreeArena(arena, PR_FALSE); return(NULL); } /* * Set a dialog string to the given string. * The source string must be writable(not a static string), and will * not be copied, so it is the responsibility of the caller to make * sure it is freed after use. */ void XP_SetDialogString(XPDialogStrings *strings, int argNum, char *string) { /* make sure we are doing it right */ PORT_Assert(argNum < strings->nargs); PORT_Assert(argNum >= 0); PORT_Assert(strings->args[argNum] == NULL); /* set the string */ strings->args[argNum] = string; return; } /* * Copy a string to the dialog string */ void XP_CopyDialogString(XPDialogStrings *strings, int argNum, const char *string) { int len; /* make sure we are doing it right */ PORT_Assert(argNum < strings->nargs); PORT_Assert(argNum >= 0); PORT_Assert(strings->args[argNum] == NULL); /* copy the string */ len = PORT_Strlen(string) + 1; strings->args[argNum] = (char *)PORT_ArenaAlloc(strings->arena, len); if ( strings->args[argNum] != NULL ) { PORT_Memcpy(strings->args[argNum], string, len); } return; } /* * free the dialog strings */ void XP_FreeDialogStrings(XPDialogStrings *strings) { PORT_FreeArena(strings->arena, PR_FALSE); return; } static XPDialogInfo alertDialog = { XP_DIALOG_OK_BUTTON, NULL, 600, 224 }; void XP_MakeHTMLAlert(void *proto_win, char *string) { XPDialogStrings *strings; /* get empty strings */ strings = XP_GetDialogStrings(XP_EMPTY_STRINGS); if ( strings == NULL ) { return; } XP_CopyDialogString(strings, 0, string); /* put up the dialog */ XP_MakeHTMLDialog(proto_win, &alertDialog, XP_ALERT_TITLE_STRING, strings, NULL, PR_FALSE); return; } /* * destroy an HTML dialog window that has not had anything written to it yet */ void XP_DestroyHTMLDialogWindow(void *window) { deleteWindowCBArg *delstate; /* set callback to destroy the window */ delstate = (deleteWindowCBArg *)PORT_Alloc(sizeof(deleteWindowCBArg)); if ( delstate ) { delstate->window = window; delstate->arg = NULL; delstate->deleteWinCallback = NULL; delstate->freeArena = NULL; (void)FE_SetTimeout(deleteWindow, (void *)delstate, 0); } return; }