mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-30 20:48:52 +00:00
1992 lines
46 KiB
C
1992 lines
46 KiB
C
/* -*- 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,
|
|
"<table width=100%><tr><td bgcolor=#0000ff><img align=left src=about:security?banner-secure></td></tr></table><br>",
|
|
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,
|
|
"<table><tr><td>"
|
|
"<img align=left src=about:security?banner-secure></td>"
|
|
"<td>", quote);
|
|
if (rv) {
|
|
return(SECFailure);
|
|
}
|
|
rv = putStringToStream(stream,
|
|
XP_GetString(XP_BANNER_FONTFACE_INFO_STRING),
|
|
quote);
|
|
if (rv) {
|
|
return(SECFailure);
|
|
}
|
|
rv = putStringToStream(stream, "<B>", quote);
|
|
if (rv) {
|
|
return(SECFailure);
|
|
}
|
|
} else if (!PORT_Strcmp(token, "sec-banner-end")) {
|
|
rv = putStringToStream(stream,
|
|
"</b></font></td></tr></table><br>", 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=PR_FALSE;
|
|
|
|
/* 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=NULL;
|
|
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=0;
|
|
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=NULL;
|
|
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
|
|
#endif
|
|
cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, &chrome);
|
|
|
|
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=0;
|
|
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;
|
|
}
|
|
|