mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
6b8d30070f
an agent that we know takes advantage of S/MIME reatures.
1298 lines
36 KiB
C
1298 lines
36 KiB
C
/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
#include "prmon.h"
|
|
#include "nlsutil.h"
|
|
#include "serv.h" /* for SSM_DEBUG */
|
|
#include "ssmerrs.h"
|
|
#include "resource.h"
|
|
#include "kgenctxt.h"
|
|
#include "textgen.h"
|
|
#include "minihttp.h"
|
|
#include "certlist.h"
|
|
#include "ssldlgs.h"
|
|
#include "oldfunc.h"
|
|
#include "pkcs11ui.h"
|
|
#include "signtextres.h"
|
|
#include "prmem.h"
|
|
#include "certres.h"
|
|
#include "advisor.h"
|
|
#include "nlslayer.h"
|
|
|
|
typedef enum
|
|
{
|
|
TEXTGEN_PUNCT_LEFTBRACE = (int) 0,
|
|
TEXTGEN_PUNCT_RIGHTBRACE,
|
|
TEXTGEN_PUNCT_SINGLEQUOTE,
|
|
TEXTGEN_PUNCT_COMMA,
|
|
TEXTGEN_PUNCT_DOLLAR,
|
|
TEXTGEN_PUNCT_SPACE,
|
|
TEXTGEN_PUNCT_PERCENT,
|
|
TEXTGEN_PUNCT_MAX_INDEX
|
|
} PunctIndex;
|
|
|
|
static char *punct_ch = "{}',$ %"; /* make this match the enum above */
|
|
|
|
typedef struct KeywordHandlerEntry
|
|
{
|
|
char *keyword;
|
|
KeywordHandlerFunc func;
|
|
} KeywordHandlerEntry;
|
|
|
|
static SSMCollection *keyword_handlers = NULL;
|
|
|
|
/* Forward declarations */
|
|
SSMStatus SSM_GetAndExpandTextKeyedByString(SSMTextGenContext *cx,
|
|
const char *key,
|
|
char **result);
|
|
/* password keyword handler */
|
|
SSMStatus SSM_ReSetPasswordKeywordHandler(SSMTextGenContext * cx);
|
|
SSMStatus SSM_ShowFollowupKeywordHandler(SSMTextGenContext * cx);
|
|
SSMStatus SSM_PasswordPrefKeywordHandler(SSMTextGenContext * cx);
|
|
|
|
/* cert renewal keyword handler */
|
|
SSMStatus SSM_RenewalCertInfoHandler(SSMTextGenContext* cx);
|
|
|
|
/* Given a string and offset of a left brace, find the matching right brace. */
|
|
static int
|
|
SSMTextGen_FindRightBrace(char *str)
|
|
{
|
|
int i, startOff = 0;
|
|
int result = -1, len;
|
|
char *raw;
|
|
|
|
if (!punct_ch[0] || !str || (startOff < 0))
|
|
return -1; /* didn't initialize earlier, or bad params */
|
|
|
|
/* Get the length of the source string */
|
|
len = PL_strlen(str);
|
|
|
|
raw = str;
|
|
|
|
/* Walk along the string until we find either a left or right brace. */
|
|
for(i=startOff+1;(i < len) && (result < 0);i++)
|
|
{
|
|
if (raw[i] == punct_ch[TEXTGEN_PUNCT_LEFTBRACE])
|
|
{
|
|
/* Another left brace. Recurse.
|
|
Assigning back to i is ok, because we'll increment
|
|
before the next check (and avoid double-counting the
|
|
terminating right brace on which i sits after
|
|
this call). */
|
|
i += SSMTextGen_FindRightBrace(&str[i]);
|
|
}
|
|
else if (raw[i] == punct_ch[TEXTGEN_PUNCT_RIGHTBRACE])
|
|
{
|
|
/* Found the end. Return now. */
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static SSMStatus
|
|
SSMTextGen_DequotifyString(char *str)
|
|
{
|
|
if (str == NULL) {
|
|
return SSM_FAILURE;
|
|
}
|
|
while ((str = PL_strchr(str, '\'')) != NULL) {
|
|
if (str[1] == '\'') {
|
|
memmove(str, &str[1], PL_strlen(&str[1])+1);
|
|
}
|
|
str++;
|
|
}
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
PRBool
|
|
SSMTextGen_StringContainsFormatParams(char *str)
|
|
{
|
|
while ((str = PL_strchr(str, punct_ch[TEXTGEN_PUNCT_PERCENT])) != NULL) {
|
|
if (isdigit(str[1])) {
|
|
return PR_TRUE;
|
|
}
|
|
str++;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
static PRInt32
|
|
SSMTextGen_CountCommas(char *str)
|
|
{
|
|
PRInt32 result = 0;
|
|
|
|
while ((str = PL_strchr(str,punct_ch[TEXTGEN_PUNCT_COMMA])) != NULL) {
|
|
result++;
|
|
str++;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Show a stack frame. */
|
|
void
|
|
SSMTextGen_Show(SSMTextGenContext *cx)
|
|
{
|
|
char *temp_ch = NULL;
|
|
|
|
temp_ch = cx->m_keyword;
|
|
SSM_DEBUG("{%s", temp_ch);
|
|
if (cx->m_params && (SSM_Count(cx->m_params) > 0))
|
|
{
|
|
char *param = (char *) SSM_At(cx->m_params, 0);
|
|
int i = 0;
|
|
while(param)
|
|
{
|
|
temp_ch = param;
|
|
printf("%c%s", ((i==0)? '/':','), temp_ch);
|
|
param = (char *) SSM_At(cx->m_params, ++i);
|
|
}
|
|
}
|
|
printf("}\n");
|
|
}
|
|
|
|
/* Trace back a text gen context. */
|
|
void
|
|
SSMTextGen_DoTraceback(SSMTextGenContext *cx)
|
|
{
|
|
|
|
if (!cx)
|
|
return;
|
|
|
|
/* Depth first traceback */
|
|
if ((cx->m_caller) && (cx->m_caller != cx))
|
|
SSMTextGen_DoTraceback(cx->m_caller);
|
|
SSMTextGen_Show(cx);
|
|
}
|
|
|
|
void
|
|
SSMTextGen_Traceback(char *reason, SSMTextGenContext *cx)
|
|
{
|
|
if (reason)
|
|
SSM_DEBUG("ERROR - %s\n", reason);
|
|
SSM_DEBUG("Traceback:\n");
|
|
if (!cx)
|
|
SSM_DEBUG("(None available)\n");
|
|
else
|
|
SSMTextGen_DoTraceback(cx);
|
|
SSM_DEBUG("-- End of traceback --\n");
|
|
}
|
|
|
|
/* Create/destroy a textgen context. */
|
|
SSMStatus
|
|
SSMTextGen_NewContext(SSMTextGenContext *caller, /* can be NULL */
|
|
HTTPRequest *req,
|
|
char *keyword,
|
|
char **params,
|
|
SSMTextGenContext **result)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
SSMTextGenContext *cx = (SSMTextGenContext *) PR_CALLOC(sizeof(SSMTextGenContext));
|
|
if (!cx)
|
|
goto loser;
|
|
|
|
/* Create the collection within the context. */
|
|
cx->m_params = SSM_NewCollection();
|
|
if (!cx->m_params)
|
|
goto loser;
|
|
|
|
cx->m_caller = caller;
|
|
cx->m_request = req;
|
|
|
|
if (keyword)
|
|
cx->m_keyword = PL_strdup(keyword);
|
|
else
|
|
cx->m_keyword = PL_strdup("");
|
|
|
|
if (cx->m_keyword == NULL)
|
|
goto loser;
|
|
|
|
cx->m_result = PL_strdup("");
|
|
|
|
if (params)
|
|
{
|
|
char *p;
|
|
PRIntn i;
|
|
|
|
for(i=0; params[i] != NULL; i++)
|
|
{
|
|
p = params[i];
|
|
if (p)
|
|
SSM_Enqueue(cx->m_params, SSM_PRIORITY_NORMAL, p);
|
|
}
|
|
}
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
if (cx)
|
|
{
|
|
if (cx->m_params)
|
|
{
|
|
/* Couldn't finish filling out the params. The parameter
|
|
strings are still owned by the caller at this point, so
|
|
clear out the collection before destroying the context. */
|
|
char *tmp;
|
|
SSMStatus trv;
|
|
|
|
/* Deallocate the parameters individually, then
|
|
destroy the parameter collection. */
|
|
trv = SSM_Dequeue(cx->m_params, SSM_PRIORITY_NORMAL,
|
|
(void **) &tmp, PR_FALSE);
|
|
while ((trv == PR_SUCCESS) && tmp)
|
|
{
|
|
trv = SSM_Dequeue(cx->m_params, SSM_PRIORITY_NORMAL,
|
|
(void **) &tmp, PR_FALSE);
|
|
}
|
|
}
|
|
SSMTextGen_DestroyContext(cx);
|
|
cx = NULL;
|
|
}
|
|
done:
|
|
*result = cx;
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMTextGen_NewTopLevelContext(HTTPRequest *req,
|
|
SSMTextGenContext **result)
|
|
{
|
|
SSMTextGenContext *cx = NULL;
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
|
|
rv = SSMTextGen_NewContext(NULL, req, NULL, NULL, &cx);
|
|
|
|
*result = cx;
|
|
return rv;
|
|
}
|
|
|
|
static SSMTextGenContext *
|
|
SSMTextGen_PushStack(SSMTextGenContext *cx,
|
|
char *key,
|
|
char **params)
|
|
{
|
|
SSMTextGenContext *newcx = NULL;
|
|
SSMStatus rv;
|
|
|
|
rv = SSMTextGen_NewContext(cx, cx->m_request, key, params, &newcx);
|
|
if (rv != SSM_SUCCESS)
|
|
SSMTextGen_Traceback("Couldn't push textgen context stack", cx);
|
|
|
|
#if 0
|
|
if (newcx)
|
|
{
|
|
SSM_DEBUG("New stack frame: ");
|
|
SSMTextGen_Show(newcx);
|
|
}
|
|
#endif
|
|
return newcx;
|
|
}
|
|
|
|
void
|
|
SSMTextGen_DestroyContext(SSMTextGenContext *cx)
|
|
{
|
|
if (cx->m_params)
|
|
{
|
|
char *tmp;
|
|
SSMStatus rv;
|
|
|
|
/* Deallocate the parameters individually, then
|
|
destroy the parameter collection. */
|
|
rv = SSM_Dequeue(cx->m_params, SSM_PRIORITY_NORMAL,
|
|
(void **) &tmp, PR_FALSE);
|
|
while ((rv == PR_SUCCESS) && tmp)
|
|
{
|
|
PR_Free(tmp);
|
|
rv = SSM_Dequeue(cx->m_params, SSM_PRIORITY_NORMAL,
|
|
(void **) &tmp, PR_FALSE);
|
|
}
|
|
SSM_DestroyCollection(cx->m_params);
|
|
}
|
|
|
|
if (cx->m_keyword)
|
|
PR_Free(cx->m_keyword);
|
|
|
|
if (cx->m_result)
|
|
PR_Free(cx->m_result);
|
|
|
|
PR_Free(cx);
|
|
}
|
|
|
|
|
|
SSMControlConnection *
|
|
SSMTextGen_GetControlConnection(SSMTextGenContext *cx)
|
|
{
|
|
if (cx && cx->m_request)
|
|
return cx->m_request->ctrlconn;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
SSMResource *
|
|
SSMTextGen_GetTargetObject(SSMTextGenContext *cx)
|
|
{
|
|
SSMResource *target = NULL;
|
|
|
|
if (cx && cx->m_request && cx->m_request->target) {
|
|
target = cx->m_request->target;
|
|
} else {
|
|
SSMControlConnection *ctrl;
|
|
ctrl = SSMTextGen_GetControlConnection(cx);
|
|
target = &(ctrl->super.super);
|
|
}
|
|
return target;
|
|
}
|
|
|
|
/* Allocate/deallocate an array of UTF8 Strings. */
|
|
static void
|
|
SSMTextGen_DeleteStringPtrArray(char **array)
|
|
{
|
|
PRInt32 i;
|
|
|
|
if (array)
|
|
{
|
|
for(i=0; array[i] != NULL; i++)
|
|
{
|
|
PR_Free(array[i]);
|
|
array[i] = NULL;
|
|
}
|
|
PR_Free(array);
|
|
}
|
|
}
|
|
|
|
/* Given a comma-delimited UnicodeString, split the first
|
|
string off and put the remainder of the fields into an array. */
|
|
static SSMStatus
|
|
SSMTextGen_SplitKeywordParams(const char *orig,
|
|
char **keywdResult,
|
|
char ***paramResult)
|
|
{
|
|
char **params = NULL;
|
|
char *keywd;
|
|
char *space, *cursor, *comma;
|
|
PRInt32 argLen;
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
PRInt32 i;
|
|
PRInt32 numParams;
|
|
|
|
/* in case we fail */
|
|
*keywdResult = NULL;
|
|
*paramResult = NULL;
|
|
|
|
if (!orig)
|
|
{
|
|
rv = PR_INVALID_ARGUMENT_ERROR;
|
|
goto loser;
|
|
}
|
|
|
|
/* Get the keyword out first. */
|
|
/* If we have parameters, copy them off. */
|
|
space = PL_strchr(orig, punct_ch[TEXTGEN_PUNCT_SPACE]);
|
|
if (space != NULL) {
|
|
char ch;
|
|
ch = space[0];
|
|
space[0] = '\0';
|
|
keywd = PL_strdup(orig);
|
|
space[0] = ch;
|
|
} else {
|
|
int len, i;
|
|
|
|
len = PL_strlen(orig);
|
|
keywd = PL_strdup(orig);
|
|
for (i=len; i>=0 && isspace(keywd[i]); i--) {
|
|
keywd = '\0';
|
|
}
|
|
}
|
|
/* Now get the parameters. */
|
|
if (space != NULL) {
|
|
cursor = space+1;
|
|
numParams = SSMTextGen_CountCommas(cursor)+2;
|
|
params = SSM_ZNEW_ARRAY(char*, numParams);
|
|
for (i=0; i<(numParams-1) && cursor != NULL; i++) {
|
|
comma = PL_strchr(cursor, punct_ch[TEXTGEN_PUNCT_COMMA]);
|
|
if (comma != NULL) {
|
|
argLen = comma-cursor;
|
|
} else {
|
|
argLen = PL_strlen(cursor);
|
|
}
|
|
params[i] = SSM_NEW_ARRAY(char, (argLen+1));
|
|
if (params[i] == NULL) {
|
|
goto loser;
|
|
}
|
|
PL_strncpy(params[i], cursor, argLen);
|
|
params[i][argLen] = '\0';
|
|
cursor = (comma == NULL) ? NULL : comma+1;
|
|
}
|
|
}
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv != SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
|
|
if (keywd)
|
|
{
|
|
PR_Free(keywd);
|
|
keywd = NULL;
|
|
}
|
|
|
|
if (params)
|
|
{
|
|
SSMTextGen_DeleteStringPtrArray(params);
|
|
params = NULL;
|
|
}
|
|
done:
|
|
*keywdResult = keywd;
|
|
*paramResult = params;
|
|
return rv;
|
|
}
|
|
|
|
/* Keyword handler routines */
|
|
static SSMStatus
|
|
SSM_KeywordHandlerInitialize(void)
|
|
{
|
|
keyword_handlers = SSM_NewCollection();
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_RegisterKeywordHandler(char *keyword,
|
|
KeywordHandlerFunc func)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
KeywordHandlerEntry *entry = NULL;
|
|
|
|
if ((!keyword_handlers) || (!keyword) || (!func))
|
|
goto loser;
|
|
|
|
entry = (KeywordHandlerEntry *) PR_CALLOC(sizeof(KeywordHandlerEntry));
|
|
if (!entry)
|
|
goto loser;
|
|
entry->keyword = keyword;
|
|
entry->func = func;
|
|
|
|
SSM_Enqueue(keyword_handlers, SSM_PRIORITY_NORMAL, entry);
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
if (entry)
|
|
PR_Free(entry);
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMTextGen_DeregisterKeywordHandler(KeywordHandlerFunc *func)
|
|
{
|
|
KeywordHandlerEntry *e, *found = NULL;
|
|
PRIntn i;
|
|
PRIntn numEntries = SSM_Count(keyword_handlers);
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
|
|
for(i=0;i<numEntries;i++)
|
|
{
|
|
e = (KeywordHandlerEntry *) SSM_At(keyword_handlers, i);
|
|
if ((e != NULL) && (e->func == (KeywordHandlerFunc) func))
|
|
{
|
|
found = e;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
rv = SSM_Remove(keyword_handlers, found);
|
|
if (rv == SSM_SUCCESS)
|
|
{
|
|
/* Deallocate (found) since we no longer need it. */
|
|
PR_Free(found);
|
|
}
|
|
}
|
|
else
|
|
rv = SSM_FAILURE;
|
|
|
|
return rv;
|
|
}
|
|
|
|
static SSMStatus
|
|
SSMTextGen_FindKeywordHandler(char *key,
|
|
KeywordHandlerFunc *func)
|
|
{
|
|
KeywordHandlerEntry *e, *found = NULL;
|
|
char *key_ch = key;
|
|
PRIntn i;
|
|
PRIntn numEntries = SSM_Count(keyword_handlers);
|
|
|
|
*func = NULL; /* in case we fail */
|
|
|
|
if (key_ch)
|
|
{
|
|
for(i=0;i<numEntries;i++)
|
|
{
|
|
e = (KeywordHandlerEntry *) SSM_At(keyword_handlers, i);
|
|
if (!PL_strcmp(e->keyword, key_ch))
|
|
{
|
|
found = e;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
*func = found->func;
|
|
|
|
return (*func ? SSM_SUCCESS : SSM_FAILURE);
|
|
}
|
|
|
|
/*
|
|
Given a numbered keyword argument in (arg), return the appropriate
|
|
argument from the textgen context.
|
|
*/
|
|
static SSMStatus
|
|
SSMTextGen_ReplaceArgument(SSMTextGenContext *cx,
|
|
char *keywd, char **dest)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
char *arg = NULL, *param = NULL, *raw;
|
|
PRInt32 argNum = -1;
|
|
|
|
/* Is the first char a $? If not, bail. */
|
|
raw = keywd;
|
|
if ((!raw) || (raw[0] != punct_ch[TEXTGEN_PUNCT_DOLLAR]))
|
|
goto loser;
|
|
|
|
/*
|
|
If we're here, this means that we think we have a numeric parameter.
|
|
Copy the keyword, lop off the first char, and convert to an arg number.
|
|
*/
|
|
arg = keywd+1;
|
|
argNum = SSMTextGen_atoi(arg);
|
|
if (argNum < 0)
|
|
goto loser;
|
|
|
|
param = (char *) SSM_At(cx->m_params, argNum-1);
|
|
if (!param)
|
|
{
|
|
SSM_DEBUG("ERROR: Wanted argument %d when only %d args present.\n",
|
|
argNum, SSM_Count(cx->m_params));
|
|
SSMTextGen_Traceback(NULL, cx);
|
|
goto loser;
|
|
}
|
|
|
|
*dest = PL_strdup(param);
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
if (*dest)
|
|
{
|
|
PR_Free(*dest);
|
|
*dest = NULL;
|
|
}
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
Given a Cartman keyword (presumably found within a string),
|
|
replace it with appropriate content.
|
|
*/
|
|
static SSMStatus
|
|
SSMTextGen_ProcessKeyword(SSMTextGenContext *cx,
|
|
char *src, char **dest)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
SSMTextGenContext *newcx = NULL;
|
|
char *keywd = NULL;
|
|
char **params = NULL;
|
|
KeywordHandlerFunc func;
|
|
|
|
*dest = NULL; /* in case we fail */
|
|
if (PL_strchr(src, '\n')) {
|
|
/* We've got some text with newlines in it. Keywords in properties
|
|
* files aren't allowed to have newlines in them.
|
|
*/
|
|
goto loser;
|
|
}
|
|
|
|
/* Split out into keyword and parameters. */
|
|
rv = SSMTextGen_SplitKeywordParams(src, &keywd, ¶ms);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
/* SSM_DebugUTF8String("SSMTextGen_ProcessKeyword - orig src", src); */
|
|
/* SSM_DebugUTF8String("SSMTextGen_ProcessKeyword - keywd", keywd); */
|
|
/* if (cx->m_params) */
|
|
/* { */
|
|
/* char buf[256]; */
|
|
/* int i = 0; */
|
|
/* UnicodeStringPtr param = NULL; */
|
|
/* for(param = SSM_At(cx->m_params, 0), i = 0; param != NULL; i++) */
|
|
/* { */
|
|
/* param = SSM_At(cx->m_params, i); */
|
|
/* if (param) */
|
|
/* { */
|
|
/* PR_snprintf(buf, 256, "SSMTextGen_ProcessKeyword - param[%d]", i+1); */
|
|
/* SSM_DebugUTF8String(buf, param); */
|
|
/* } */
|
|
/* } */
|
|
/* } */
|
|
|
|
/* If this is a numbered parameter, replace it with
|
|
what we have stored in the textgen context. */
|
|
rv = SSMTextGen_ReplaceArgument(cx, keywd, dest);
|
|
if (rv == SSM_SUCCESS)
|
|
goto done;
|
|
|
|
/* Push the textgen stack. */
|
|
newcx = SSMTextGen_PushStack(cx, keywd, params);
|
|
if (!newcx)
|
|
goto loser;
|
|
|
|
/* SSMTextGen_PushStack puts the args of params into a
|
|
* collection. So we can now free the array since the
|
|
* individual pointers are stored in a collection
|
|
*/
|
|
PR_Free(params);
|
|
params = NULL;
|
|
|
|
/* Look for a keyword handler. */
|
|
rv = SSMTextGen_FindKeywordHandler(keywd, &func);
|
|
if ((rv == SSM_SUCCESS) && (func))
|
|
{
|
|
/* Run the keyword handler. */
|
|
rv = (*func)(newcx);
|
|
if (rv != SSM_SUCCESS)
|
|
{
|
|
SSMTextGen_Traceback("Keyword handler returned error %d", newcx);
|
|
goto loser;
|
|
}
|
|
|
|
*dest = newcx->m_result;
|
|
newcx->m_result = NULL; /* so the memory doesn't get deallocated now */
|
|
|
|
goto done;
|
|
}
|
|
|
|
/* Treat (keywd) as the name of a string in the properties
|
|
file. Extract the value, expand it, and return it (if there
|
|
is something available). (This pushes the textgen stack.) */
|
|
rv = SSM_GetAndExpandTextKeyedByString(newcx, keywd, dest);
|
|
if (rv == SSM_SUCCESS)
|
|
goto done;
|
|
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
if (*dest)
|
|
{
|
|
PR_Free(*dest);
|
|
*dest = NULL;
|
|
}
|
|
done:
|
|
if (keywd)
|
|
PR_Free(keywd);
|
|
if (newcx)
|
|
SSMTextGen_DestroyContext(newcx);
|
|
/* if (params && !newcx) */
|
|
/* SSMTextGen_DeleteStringPtrArray(params); */
|
|
return rv;
|
|
}
|
|
|
|
typedef struct SSMTextGenResultStr {
|
|
char *result;
|
|
int allocSize, curSize;
|
|
} SSMTextGenResult;
|
|
|
|
SSMStatus
|
|
ssmtextgen_init_segresult(SSMTextGenResult *result, int origLen)
|
|
{
|
|
memset (result, 0, sizeof(SSMTextGenResult));
|
|
result->allocSize = (int)(origLen*1.5);
|
|
result->result = SSM_NEW_ARRAY(char, result->allocSize+1);
|
|
if (result->result == NULL) {
|
|
return SSM_FAILURE;
|
|
}
|
|
result->result[0] = '\0';
|
|
result->curSize = 0;
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
ssmtextgen_add_segment(SSMTextGenResult *result, char *segment)
|
|
{
|
|
int segLen;
|
|
|
|
segLen = PL_strlen(segment);
|
|
if ((result->curSize+segLen) > result->allocSize) {
|
|
char *newString;
|
|
int newLen, defReallocLen, newSegReallocLen;
|
|
|
|
defReallocLen = result->allocSize*2;
|
|
newSegReallocLen = segLen + result->curSize;
|
|
newLen = (defReallocLen > newSegReallocLen) ? defReallocLen :
|
|
newSegReallocLen * 2;
|
|
newString = (char *) PR_Realloc(result->result, newLen);
|
|
if (newString == NULL) {
|
|
return SSM_FAILURE;
|
|
}
|
|
result->result = newString;
|
|
result->allocSize = newLen;
|
|
}
|
|
memcpy(&result->result[result->curSize], segment, segLen);
|
|
result->curSize += segLen;
|
|
result->result[result->curSize] = '\0';
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
Perform substitutions for non-numeric parameters in (str). Parameters
|
|
in the text are surrounded by curly braces.
|
|
*/
|
|
SSMStatus
|
|
SSMTextGen_SubstituteString(SSMTextGenContext *cx,
|
|
char *str, char **result)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
int len, fragLen, rightBraceIndex;
|
|
char *repl1 = NULL, *repl2 = NULL;
|
|
char *leftBrace, *rightBrace;
|
|
char *tmp, *raw;
|
|
SSMTextGenResult segResult;
|
|
|
|
/* in case we fail */
|
|
*result = NULL;
|
|
|
|
if ((!str) || (!result))
|
|
return SSM_FAILURE;
|
|
|
|
/* Get the length of the source string, and a ptr into it */
|
|
raw = str;
|
|
len = PL_strlen(raw);
|
|
|
|
if (ssmtextgen_init_segresult(&segResult, len) != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
/* Scan the string for the next keyword, if any. */
|
|
while (1)
|
|
{
|
|
/* First look for the left brace */
|
|
leftBrace = PL_strchr(raw, punct_ch[TEXTGEN_PUNCT_LEFTBRACE]);
|
|
if (leftBrace == NULL) {
|
|
if (ssmtextgen_add_segment(&segResult, raw) !=
|
|
SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
break;
|
|
}
|
|
/* Look for the corresponding right brace. */
|
|
rightBraceIndex = SSMTextGen_FindRightBrace(leftBrace);
|
|
if (rightBraceIndex >= len) {
|
|
/* No corresponding right brace, should ignore this one. */
|
|
/* We can stop processing here. */
|
|
if (ssmtextgen_add_segment(&segResult, raw) !=
|
|
SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
break;
|
|
}
|
|
/* Process the keyword. */
|
|
/* Get all of the text between the braces and expand it. */
|
|
rightBrace = &leftBrace[rightBraceIndex];
|
|
fragLen = rightBraceIndex;
|
|
tmp = SSM_NEW_ARRAY(char, fragLen);
|
|
if (tmp == NULL) {
|
|
goto loser;
|
|
}
|
|
memcpy(tmp, leftBrace+1, fragLen-1);
|
|
tmp[fragLen-1] = '\0';
|
|
rv = SSMTextGen_SubstituteString(cx, tmp, &repl1);
|
|
PR_Free(tmp);
|
|
tmp = NULL;
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSMTextGen_ProcessKeyword(cx, repl1, &repl2);
|
|
if (rv != SSM_SUCCESS) {
|
|
char ch;
|
|
SSMStatus rv1, rv2;
|
|
/* The text between the braces couldn't be replaced, so
|
|
* insert everything starting with raw up to and including
|
|
* the left brace, then insert repl1 which is what the substring
|
|
* was substituted as, then place the closing right bracket.
|
|
*/
|
|
ch = leftBrace[1];
|
|
leftBrace[1] = '\0';
|
|
rv1 = ssmtextgen_add_segment(&segResult, raw);
|
|
leftBrace[1] = ch;
|
|
rv2 = ssmtextgen_add_segment(&segResult, repl1);
|
|
if (rv1 != SSM_SUCCESS || rv2 != SSM_SUCCESS ||
|
|
ssmtextgen_add_segment(&segResult, "}") != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
} else {
|
|
/* We processed a keyword, so take the string before the left
|
|
* brace, make it the next segment, then make the response
|
|
* from SSMTextGen_ProcessKeyword the segment after that.
|
|
*/
|
|
SSMStatus rv1, rv2;
|
|
|
|
leftBrace[0] = '\0';
|
|
rv1 = ssmtextgen_add_segment(&segResult, raw);
|
|
rv2 = ssmtextgen_add_segment(&segResult, repl2);
|
|
PR_Free(repl2);
|
|
repl2 = NULL;
|
|
leftBrace[0] = punct_ch[TEXTGEN_PUNCT_LEFTBRACE];
|
|
if (rv1 != SSM_SUCCESS || rv2 != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
}
|
|
if (repl1 != NULL) {
|
|
PR_Free(repl1);
|
|
repl1 = NULL;
|
|
}
|
|
if (repl2 != NULL) {
|
|
PR_Free(repl2);
|
|
repl2 = NULL;
|
|
}
|
|
raw = &rightBrace[1];
|
|
}
|
|
*result = segResult.result;
|
|
rv = SSM_SUCCESS;
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
|
|
|
|
/* delete/NULL result if we ran into a problem */
|
|
if (*result)
|
|
{
|
|
PR_Free(*result);
|
|
*result = NULL;
|
|
}
|
|
done:
|
|
/* deallocate working strings */
|
|
return rv;
|
|
}
|
|
|
|
/* Given a key and a context, cycle through resource bundles until
|
|
we find a match for the desired key. */
|
|
SSMStatus
|
|
SSM_FindUTF8StringInBundles(SSMTextGenContext *cx,
|
|
const char *key,
|
|
char **utf8Result)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char *utf8;
|
|
|
|
/* Attempt to get the string. */
|
|
utf8 = nlsGetUTF8String(key);
|
|
if (utf8) {
|
|
rv = SSMTextGen_DequotifyString(utf8); /* found it */
|
|
*utf8Result = utf8;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
/* Get a UnicodeString from the resource database and expand it. */
|
|
SSMStatus
|
|
SSM_GetAndExpandText(SSMTextGenContext *cx,
|
|
const char *key,
|
|
char **result)
|
|
{
|
|
char *replText = NULL;
|
|
char *origText=NULL;
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
|
|
if (!key || !result)
|
|
goto loser;
|
|
PR_FREEIF(*result);
|
|
*result = NULL; /* in case we fail */
|
|
|
|
if (cx != NULL && PL_strcmp(cx->m_keyword, key)) {
|
|
PR_Free(cx->m_keyword);
|
|
cx->m_keyword = PL_strdup(key);
|
|
}
|
|
|
|
/* Get the text from the database. */
|
|
SSM_DEBUG("Requesting string <%s> from the text database.\n", key);
|
|
/*nrv = NLS_PropertyResourceBundleGetString(nls_bndl,
|
|
key,
|
|
origText);*/
|
|
rv = SSM_FindUTF8StringInBundles(cx, key, &origText);
|
|
if (rv != SSM_SUCCESS)
|
|
{
|
|
if (cx != NULL)
|
|
SSM_HTTPReportSpecificError(cx->m_request,
|
|
"SSM_GetAndExpandText: SSM error %d "
|
|
"getting property string '%s'.",
|
|
rv, key);
|
|
goto loser;
|
|
}
|
|
|
|
/* Expand/replace keywords in the string. */
|
|
rv = SSMTextGen_SubstituteString(cx, origText, &replText);
|
|
/* SSM_DebugUTF8String("SSM_GetAndExpandText - expanded text", */
|
|
/* replText); */
|
|
if ((rv != SSM_SUCCESS) || (!replText))
|
|
goto loser;
|
|
*result = replText;
|
|
replText = NULL; /* So we don't free it*/
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
/* ### mwelch Need to attempt to return a blank string in case some
|
|
errors happen (such as: we can't find the string/locale not supported).*/
|
|
if (*result) {
|
|
PR_Free(*result);
|
|
*result = NULL;
|
|
}
|
|
done:
|
|
/* Dispose of intermediate strings if applicable. */
|
|
if (origText)
|
|
PR_Free(origText);
|
|
if (replText)
|
|
PR_Free(replText);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* Get a string from the resource database using a Unicode string
|
|
as key. Then, expand the string. */
|
|
SSMStatus
|
|
SSM_GetAndExpandTextKeyedByString(SSMTextGenContext *cx,
|
|
const char *key,
|
|
char **result)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
char *text=NULL;
|
|
|
|
*result = NULL; /* in case we fail */
|
|
|
|
/* Use the ascii equivalent of (key) as the actual key. */
|
|
if (!key)
|
|
goto loser;
|
|
|
|
/* Now, call SSM_GetAndExpandText above using the ASCII key. */
|
|
rv = SSM_GetAndExpandText(cx, key, &text);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
*result = text;
|
|
text = NULL;
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
if (text != NULL)
|
|
PR_Free(text);
|
|
*result = NULL;
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
/* Get a numeric parameter from the properties file. */
|
|
SSMStatus
|
|
SSM_GetNumber(SSMTextGenContext *cx, char *key, PRInt32 *param)
|
|
{
|
|
char *text = NULL;
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
|
|
*param = 0; /* in case we fail */
|
|
|
|
/* Get expanded text from the database. */
|
|
rv = SSM_GetAndExpandText(cx, key, &text);
|
|
if ((rv != SSM_SUCCESS) || (!text))
|
|
goto loser;
|
|
|
|
*param = SSMTextGen_atoi(text);
|
|
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
done:
|
|
if (text)
|
|
PR_Free(text);
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
Top level routine called by non-NLS-using parts of Cartman.
|
|
Retrieves a string, expands it, then formats it according to the
|
|
_Print method of the target object.
|
|
*/
|
|
SSMStatus
|
|
SSM_GetUTF8Text(SSMTextGenContext *cx,
|
|
const char *key,
|
|
char **resultStr)
|
|
{
|
|
char *expandedText = NULL, *fmtResult = NULL;
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
SSMResource *targetObj;
|
|
|
|
*resultStr = NULL; /* in case we fail */
|
|
|
|
/* Get expanded text from the database. */
|
|
rv = SSM_GetAndExpandText(cx, key, &expandedText);
|
|
if ((rv != SSM_SUCCESS) || (!expandedText))
|
|
goto loser;
|
|
|
|
targetObj = SSMTextGen_GetTargetObject(cx);
|
|
if (SSMTextGen_StringContainsFormatParams(expandedText))
|
|
{
|
|
if (targetObj != NULL)
|
|
rv = SSM_MessageFormatResource(targetObj, expandedText,
|
|
cx->m_request->numParams-2,
|
|
&(cx->m_request->paramValues[2]),
|
|
&fmtResult);
|
|
else
|
|
{
|
|
PR_ASSERT(!"No target object for formatting");
|
|
rv = SSM_FAILURE;
|
|
}
|
|
} else {
|
|
fmtResult = expandedText;
|
|
}
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
*resultStr = fmtResult;
|
|
|
|
if (*resultStr == NULL) {
|
|
goto loser;
|
|
}
|
|
goto done;
|
|
loser:
|
|
if (rv != SSM_SUCCESS) rv = SSM_FAILURE;
|
|
if (*resultStr != NULL) {
|
|
PR_Free(*resultStr);
|
|
}
|
|
*resultStr = NULL;
|
|
done:
|
|
if ((expandedText) && (*resultStr != expandedText))
|
|
PR_Free(expandedText);
|
|
if ((fmtResult) && (*resultStr != fmtResult))
|
|
PR_Free(fmtResult);
|
|
return rv;
|
|
}
|
|
|
|
void
|
|
TestNLS(void)
|
|
{
|
|
char *ustr;
|
|
SSMTextGenContext *cx;
|
|
SSMStatus rv;
|
|
|
|
rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
|
|
SSM_GetUTF8Text(cx, "testnls", &ustr);
|
|
SSM_DebugUTF8String("Expanded testnls", ustr);
|
|
PR_FREEIF(ustr);
|
|
SSM_GetUTF8Text(cx, "top1_content", &ustr);
|
|
SSM_DebugUTF8String("Expanded top1", ustr);
|
|
PR_FREEIF(ustr);
|
|
SSM_GetUTF8Text(cx, "left3-1_content", &ustr);
|
|
SSM_DebugUTF8String("Expanded left3-1", ustr);
|
|
PR_FREEIF(ustr);
|
|
SSMTextGen_DestroyContext(cx);
|
|
}
|
|
|
|
/*
|
|
Hello World keyword handler example.
|
|
This handler replaces all instances of the keyword "{hello}"
|
|
with "Hello, World!" in the text being processed. Look for
|
|
"Hello World" in minihttp.c for content handler examples.
|
|
*/
|
|
SSMStatus
|
|
SSM_HelloKeywordHandler(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS; /* generic rv */
|
|
|
|
cx->m_result = PL_strdup("Hello, World");
|
|
/* All done. */
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
wrap_test(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
char *p, *pattern, *temp = NULL, *fmt;
|
|
int i;
|
|
|
|
pattern = PL_strdup("test(%1$s) ");
|
|
/* Zero out the result. */
|
|
SSMTextGen_UTF8StringClear(&cx->m_result);
|
|
|
|
/* Wrap the parameters inside "test()", and concatenate them onto the
|
|
result. */
|
|
for(i=0;i<SSM_Count(cx->m_params);i++)
|
|
{
|
|
p = (char *) SSM_At(cx->m_params, i);
|
|
temp = PR_smprintf(pattern, p);
|
|
if (temp == NULL) {
|
|
goto loser;
|
|
}
|
|
fmt = PR_smprintf("%s%s", cx->m_result, temp);
|
|
PR_smprintf_free(temp);
|
|
if (fmt == NULL) {
|
|
goto loser;
|
|
}
|
|
PR_Free(cx->m_result);
|
|
cx->m_result = fmt;
|
|
}
|
|
goto done;
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
SSMTextGen_UTF8StringClear(&cx->m_result);
|
|
done:
|
|
PR_FREEIF(temp);
|
|
return rv;
|
|
}
|
|
|
|
void SSM_InitNLS(char *dataDirectory)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
|
|
/* Initialize hash table which contains keyword handlers. */
|
|
rv = SSM_KeywordHandlerInitialize();
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Create keyword handlers */
|
|
SSM_RegisterKeywordHandler("_certlist", SSM_CertListKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_server_cert_info",
|
|
SSM_ServerCertKeywordHandler);
|
|
SSM_RegisterKeywordHandler("view_cert_info",
|
|
SSM_ViewCertInfoKeywordHandler);
|
|
SSM_RegisterKeywordHandler("tokenList", SSMTokenUI_KeywordHandler);
|
|
|
|
SSM_RegisterKeywordHandler("_client_auth_certList",
|
|
SSM_ClientAuthCertListKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_get_current_time",
|
|
SSM_CurrentTimeKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_server_cert_domain_info",
|
|
SSM_ServerAuthDomainNameKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_verify_server_cert",
|
|
SSM_VerifyServerCertKeywordHandler);
|
|
|
|
SSM_RegisterKeywordHandler("_fipsmode", SSM_PKCS11FIPSModeKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_pk11modules",
|
|
SSM_PKCS11ModulesKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_pk11slots",
|
|
SSM_PKCS11SlotsKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_signtext_certList",
|
|
SSM_SignTextCertListKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_ca_cert_info", SSM_CACertKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_ca_policy_info", SSM_CAPolicyKeywordHandler);
|
|
SSM_RegisterKeywordHandler("verify_cert", SSM_VerifyCertKeywordHandler);
|
|
SSM_RegisterKeywordHandler("choose_list", SSM_SelectCertKeywordHandler);
|
|
SSM_RegisterKeywordHandler("edit_cert", SSM_EditCertKeywordHandler);
|
|
SSM_RegisterKeywordHandler("sa_selected_item", SSMSecurityAdvisorContext_sa_selected_item);
|
|
SSM_RegisterKeywordHandler("set_or_reset_password", SSM_ReSetPasswordKeywordHandler);
|
|
SSM_RegisterKeywordHandler("show_result", SSM_ShowFollowupKeywordHandler);
|
|
SSM_RegisterKeywordHandler("get_pref_list", SSMSecurityAdvisorContext_GetPrefListKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_ocsp_options",
|
|
SSM_OCSPOptionsKeywordHandler);
|
|
SSM_RegisterKeywordHandler("_default_ocsp_responder",
|
|
SSM_OCSPDefaultResponderKeywordHandler);
|
|
SSM_RegisterKeywordHandler("password_lifetime_pref", SSM_PasswordPrefKeywordHandler);
|
|
SSM_RegisterKeywordHandler("delete_cert_help", SSM_DeleteCertHelpKeywordHandler);
|
|
SSM_RegisterKeywordHandler("delete_cert_warning", SSM_DeleteCertWarnKeywordHandler);
|
|
SSM_RegisterKeywordHandler("get_new_cert_url", SSM_ObtainNewCertSite);
|
|
SSM_RegisterKeywordHandler("ldap_server_list", SSM_LDAPServerListKeywordHandler);
|
|
#if 0
|
|
SSM_RegisterKeywordHandler("_java_principals", SSM_JavaPrincipalsKeywordHandler);
|
|
#endif
|
|
#if 0
|
|
SSM_RegisterKeywordHandler("testwrap", wrap_test);
|
|
SSM_RegisterKeywordHandler("hello", SSM_HelloKeywordHandler);
|
|
#endif
|
|
SSM_RegisterKeywordHandler("free_target",
|
|
SSM_FreeTarget);
|
|
SSM_RegisterKeywordHandler("pkcs12_incompatibility_warning",
|
|
SSM_WarnPKCS12Incompatibility);
|
|
SSM_RegisterKeywordHandler("pass_var",
|
|
SSM_PassVariable);
|
|
SSM_RegisterKeywordHandler("_ocsp_responder_list",
|
|
SSM_OCSPResponderList);
|
|
SSM_RegisterKeywordHandler("_renewal_cert_info",
|
|
SSM_RenewalCertInfoHandler);
|
|
SSM_RegisterKeywordHandler("_emailAddresses",
|
|
SSM_FillTextWithEmails);
|
|
SSM_RegisterKeywordHandler("_certIssuerWindowName",
|
|
SSM_MakeUniqueNameForIssuerWindow);
|
|
SSM_RegisterKeywordHandler("_windowOffset",
|
|
SSM_GetWindowOffset);
|
|
SSM_RegisterKeywordHandler("_crlButton",
|
|
SSM_DisplayCRLButton);
|
|
SSM_RegisterKeywordHandler("_crlList",
|
|
SSM_ListCRLs);
|
|
SSM_RegisterKeywordHandler("_smime_tab",
|
|
SSM_LayoutSMIMETab);
|
|
SSM_RegisterKeywordHandler("_java_js_tab",
|
|
SSM_LayoutJavaJSTab);
|
|
SSM_RegisterKeywordHandler("_addOthersCerts",
|
|
SSM_LayoutOthersTab);
|
|
#if 0
|
|
TestNLS();
|
|
#endif
|
|
return;
|
|
loser:
|
|
SSM_DEBUG("NLS initialization failed. UI will be broken.\n");
|
|
/* Run our little test. */
|
|
/*SSM_TestNLS();*/
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_PassVariable(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv;
|
|
char *variable, *value;
|
|
|
|
variable = (char *) SSM_At(cx->m_params, 0);
|
|
rv = SSM_HTTPParamValue(cx->m_request, variable, &value);
|
|
PR_FREEIF(cx->m_result);
|
|
if (rv == SSM_SUCCESS) {
|
|
cx->m_result = PR_smprintf("&%s=%s", variable, value);
|
|
} else {
|
|
cx->m_result = PL_strdup("");
|
|
}
|
|
return SSM_SUCCESS;
|
|
}
|