Files
Mozilla/mozilla/extensions/wallet/src/wallet.cpp
morse%netscape.com 8219d0c6ad remove xp_list dependency
git-svn-id: svn://10.0.0.236/trunk@43476 18797224-902f-48f8-a5cc-f745e15eee43
1999-08-18 05:49:20 +00:00

2839 lines
79 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/*
wallet.cpp
*/
#include "wallet.h"
#ifndef NECKO
#include "nsINetService.h"
#else
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsIChannel.h"
#endif // NECKO
#include "nsIServiceManager.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIURL.h"
#include "nsFileStream.h"
#include "nsSpecialSystemDirectory.h"
#include "nsINetSupportDialogService.h"
#include "nsIStringBundle.h"
#include "nsILocale.h"
#include "nsIFileLocator.h"
#include "nsIFileSpec.h"
#include "nsFileLocations.h"
#include "prmem.h"
#include "prprf.h"
#include "nsIProfile.h"
#include "nsIContent.h"
#include "nsVoidArray.h"
static NS_DEFINE_IID(kIDOMHTMLDocumentIID, NS_IDOMHTMLDOCUMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID);
#ifndef NECKO
static NS_DEFINE_IID(kINetServiceIID, NS_INETSERVICE_IID);
static NS_DEFINE_IID(kNetServiceCID, NS_NETSERVICE_CID);
#else
static NS_DEFINE_IID(kIIOServiceIID, NS_IIOSERVICE_IID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#endif // NECKO
static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
static NS_DEFINE_CID(kProfileCID, NS_PROFILE_CID);
static NS_DEFINE_IID(kIStringBundleServiceIID, NS_ISTRINGBUNDLESERVICE_IID);
static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
static NS_DEFINE_IID(kIFileLocatorIID, NS_IFILELOCATOR_IID);
static NS_DEFINE_CID(kFileLocatorCID, NS_FILELOCATOR_CID);
#include "prlong.h"
#include "prinrval.h"
/*************************************
* Code that really belongs in necko *
*************************************/
#ifdef WIN32
#include <windows.h>
#endif
#include "nsFileStream.h"
#include "nsIFileSpec.h"
#include "nsIEventQueueService.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamObserver.h"
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsIURI.h"
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
#ifdef ReallyInNecko
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#endif
static int gKeepRunning = 0;
static nsIEventQueue* gEventQ = nsnull;
class InputConsumer : public nsIStreamListener
{
public:
InputConsumer();
virtual ~InputConsumer();
// ISupports interface...
NS_DECL_ISUPPORTS
// IStreamListener interface...
NS_IMETHOD OnStartRequest(nsIChannel* channel, nsISupports* context);
NS_IMETHOD OnDataAvailable(nsIChannel* channel, nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength);
NS_IMETHOD OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg);
NS_IMETHOD Init(nsFileSpec dirSpec, const char *out);
nsOutputFileStream *mOutFile;
};
InputConsumer::InputConsumer():
mOutFile(nsnull)
{
NS_INIT_REFCNT();
}
InputConsumer::~InputConsumer()
{
if (mOutFile) {
delete mOutFile;
}
}
NS_IMPL_ISUPPORTS(InputConsumer,nsCOMTypeInfo<nsIStreamListener>::GetIID());
NS_IMETHODIMP
InputConsumer::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
if (! mOutFile->is_open())
{
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
InputConsumer::OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
char buf[1001];
PRUint32 amt;
nsresult rv;
do {
rv = aIStream->Read(buf, 1000, &amt);
if (rv == NS_BASE_STREAM_EOF) break;
if (NS_FAILED(rv)) return rv;
buf[amt] = '\0';
mOutFile->write(buf,amt);
} while (amt);
return NS_OK;
}
NS_IMETHODIMP
InputConsumer::OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg)
{
if (mOutFile) {
mOutFile->flush();
mOutFile->close();
}
gKeepRunning = 0;
return NS_OK;
}
NS_IMETHODIMP
InputConsumer::Init(nsFileSpec dirSpec, const char *out)
{
mOutFile = new nsOutputFileStream(dirSpec+out);
return NS_OK;
}
#ifdef ReallyInNecko
NECKO_EXPORT(nsresult)
#else
nsresult
#endif
NS_NewURItoFile(const char *in, nsFileSpec dirSpec, const char *out)
{
nsresult rv;
gKeepRunning = 0;
// Create the Event Queue for this thread...
NS_WITH_SERVICE(nsIEventQueueService, eventQService,
kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &gEventQ);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIURI> pURL;
rv = serv->NewURI(in, nsnull, getter_AddRefs(pURL));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIChannel> pChannel;
// Async reading thru the calls of the event sink interface
rv = serv->NewChannelFromURI("load", pURL, nsnull,
getter_AddRefs(pChannel));
if (NS_FAILED(rv)) {
printf("ERROR: NewChannelFromURI failed for %s\n", in);
return rv;
}
InputConsumer* listener;
listener = new InputConsumer;
NS_IF_ADDREF(listener);
if (!listener) {
NS_ERROR("Failed to create a new stream listener!");
return NS_ERROR_OUT_OF_MEMORY;;
}
rv = listener->Init(dirSpec, out);
if (NS_FAILED(rv)) {
NS_RELEASE(listener);
return rv;
}
rv = pChannel->AsyncRead(0, // starting position
-1, // number of bytes to read
nsnull, // ISupports context
listener); // IStreamListener consumer
if (NS_SUCCEEDED(rv)) {
gKeepRunning = 1;
}
NS_RELEASE(listener);
if (NS_FAILED(rv)) return rv;
// Enter the message pump to allow the URL load to proceed.
while ( gKeepRunning ) {
#ifdef WIN32
MSG msg;
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
gKeepRunning = 0;
}
#else
PLEvent *gEvent;
rv = gEventQ->GetEvent(&gEvent);
if (NS_SUCCEEDED(rv)) {
rv = gEventQ->HandleEvent(gEvent);
}
#endif /* !WIN32 */
}
return rv;
}
/***************************************************/
/* The following declarations define the data base */
/***************************************************/
enum PlacementType {DUP_IGNORE, DUP_OVERWRITE, DUP_BEFORE, DUP_AFTER, AT_END};
typedef struct _wallet_MapElement {
nsAutoString * item1;
nsAutoString * item2;
nsVoidArray * itemList;
} wallet_MapElement;
typedef struct _wallet_Sublist {
nsAutoString * item;
} wallet_Sublist;
PRIVATE nsVoidArray * wallet_URLFieldToSchema_list=0;
PRIVATE nsVoidArray * wallet_specificURLFieldToSchema_list=0;
PRIVATE nsVoidArray * wallet_FieldToSchema_list=0;
PRIVATE nsVoidArray * wallet_SchemaToValue_list=0;
PRIVATE nsVoidArray * wallet_SchemaConcat_list=0;
PRIVATE nsVoidArray * wallet_URL_list = 0;
#define LIST_COUNT(list) (list ? list->Count() : 0)
#define NO_CAPTURE 0
#define NO_PREVIEW 1
typedef struct _wallet_PrefillElement {
nsIDOMHTMLInputElement* inputElement;
nsIDOMHTMLSelectElement* selectElement;
nsAutoString * schema;
nsAutoString * value;
PRInt32 selectIndex;
PRUint32 count;
} wallet_PrefillElement;
/***********************************************************/
/* The following routines are for diagnostic purposes only */
/***********************************************************/
#ifdef DEBUG
void
wallet_Pause(){
fprintf(stdout,"%cpress y to continue\n", '\007');
char c;
for (;;) {
c = getchar();
if (tolower(c) == 'y') {
fprintf(stdout,"OK\n");
break;
}
}
while (c != '\n') {
c = getchar();
}
}
void
wallet_DumpAutoString(nsAutoString as){
char s[100];
as.ToCString(s, 100);
fprintf(stdout, "%s\n", s);
}
void
wallet_Dump(nsVoidArray * list) {
wallet_MapElement * ptr;
char item1[100];
char item2[100];
char item[100];
PRInt32 count = LIST_COUNT(list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_MapElement*, list->ElementAt(i));
ptr->item1->ToCString(item1, 100);
ptr->item2->ToCString(item2, 100);
fprintf(stdout, "%s %s \n", item1, item2);
wallet_Sublist * ptr1;
PRInt32 count = LIST_COUNT(ptr->itemList);
for (PRInt32 i=0; i<count; i++) {
ptr1 = NS_STATIC_CAST(wallet_Sublist*, ptr->itemList->ElementAt(i));
ptr1->item->ToCString(item, 100);
fprintf(stdout, " %s \n", item);
}
}
wallet_Pause();
}
/******************************************************************/
/* The following diagnostic routines are for timing purposes only */
/******************************************************************/
const PRInt32 timing_max = 1000;
PRInt64 timings [timing_max];
char timingID [timing_max];
PRInt32 timing_index = 0;
PRInt64 stopwatch = LL_Zero();
PRInt64 stopwatchBase;
PRBool stopwatchRunning = PR_FALSE;
void
wallet_ClearTiming() {
timing_index = 0;
}
void
wallet_DumpTiming() {
PRInt32 i, r4;
PRInt64 r1, r2, r3;
for (i=1; i<timing_index; i++) {
#ifndef XP_MAC
LL_SUB(r1, timings[i], timings[i-1]);
LL_I2L(r2, 100);
LL_DIV(r3, r1, r2);
LL_L2I(r4, r3);
fprintf(stdout, "time %c = %ld\n", timingID[i], (long)r4);
#endif
if (i%20 == 0) {
wallet_Pause();
}
}
wallet_Pause();
}
void
wallet_AddTiming(char c) {
if (timing_index<timing_max) {
timingID[timing_index] = c;
#ifndef XP_MAC
// note: PR_IntervalNow returns a 32 bit value!
LL_I2L(timings[timing_index++], PR_IntervalNow());
#endif
}
}
void
wallet_ClearStopwatch() {
stopwatch = LL_Zero();
stopwatchRunning = PR_FALSE;
}
void
wallet_ResumeStopwatch() {
if (!stopwatchRunning) {
#ifndef XP_MAC
// note: PR_IntervalNow returns a 32 bit value!
LL_I2L(stopwatchBase, PR_IntervalNow());
#endif
stopwatchRunning = PR_TRUE;
}
}
void
wallet_PauseStopwatch() {
PRInt64 r1, r2;
if (stopwatchRunning) {
#ifndef XP_MAC
// note: PR_IntervalNow returns a 32 bit value!
LL_I2L(r1, PR_IntervalNow());
LL_SUB(r2, r1, stopwatchBase);
LL_ADD(stopwatch, stopwatch, r2);
#endif
stopwatchRunning = PR_FALSE;
}
}
void
wallet_DumpStopwatch() {
PRInt64 r1, r2;
PRInt32 r3;
if (stopwatchRunning) {
#ifndef XP_MAC
// note: PR_IntervalNow returns a 32 bit value!
LL_I2L(r1, PR_IntervalNow());
LL_SUB(r2, r1, stopwatchBase);
LL_ADD(stopwatch, stopwatch, r2);
LL_I2L(stopwatchBase, PR_IntervalNow());
#endif
}
#ifndef XP_MAC
LL_I2L(r1, 100);
LL_DIV(r2, stopwatch, r1);
LL_L2I(r3, r2);
fprintf(stdout, "stopwatch = %ld\n", (long)r3);
#endif
}
#endif /* DEBUG */
/********************************************************/
/* The following data and procedures are for preference */
/********************************************************/
typedef int (*PrefChangedFunc) (const char *, void *);
extern void
SI_RegisterCallback(const char* domain, PrefChangedFunc callback, void* instance_data);
extern PRBool
SI_GetBoolPref(const char * prefname, PRBool defaultvalue);
static const char *pref_captureForms =
"wallet.captureForms";
PRIVATE Bool wallet_captureForms = PR_FALSE;
PRIVATE void
wallet_SetFormsCapturingPref(Bool x)
{
/* do nothing if new value of pref is same as current value */
if (x == wallet_captureForms) {
return;
}
/* change the pref */
wallet_captureForms = x;
}
MODULE_PRIVATE int PR_CALLBACK
wallet_FormsCapturingPrefChanged(const char * newpref, void * data)
{
PRBool x;
x = SI_GetBoolPref(pref_captureForms, PR_TRUE);
wallet_SetFormsCapturingPref(x);
return 0; /* this is PREF_NOERROR but we no longer include prefapi.h */
}
void
wallet_RegisterCapturePrefCallbacks(void)
{
PRBool x;
static Bool first_time = PR_TRUE;
if(first_time)
{
first_time = PR_FALSE;
x = SI_GetBoolPref(pref_captureForms, PR_TRUE);
wallet_SetFormsCapturingPref(x);
SI_RegisterCallback(pref_captureForms, wallet_FormsCapturingPrefChanged, NULL);
}
}
PRIVATE Bool
wallet_GetFormsCapturingPref(void)
{
wallet_RegisterCapturePrefCallbacks();
return wallet_captureForms;
}
/*************************************************************************/
/* The following routines are used for accessing strings to be localized */
/*************************************************************************/
#define TEST_URL "resource:/res/wallet.properties"
PUBLIC char*
Wallet_Localize(char* genericString) {
nsresult ret;
nsAutoString v("");
/* create a URL for the string resource file */
#ifndef NECKO
nsINetService* pNetService = nsnull;
ret = nsServiceManager::GetService(kNetServiceCID, kINetServiceIID,
(nsISupports**) &pNetService);
#else
nsIIOService* pNetService = nsnull;
ret = nsServiceManager::GetService(kIOServiceCID, kIIOServiceIID,
(nsISupports**) &pNetService);
#endif // NECKO
if (NS_FAILED(ret)) {
printf("cannot get net service\n");
return v.ToNewCString();
}
nsIURI *url = nsnull;
#ifndef NECKO
ret = pNetService->CreateURL(&url, nsString(TEST_URL), nsnull, nsnull,
nsnull);
nsServiceManager::ReleaseService(kNetServiceCID, pNetService);
#else
nsIURI *uri = nsnull;
ret = pNetService->NewURI(TEST_URL, nsnull, &uri);
if (NS_FAILED(ret)) {
printf("cannot create URI\n");
nsServiceManager::ReleaseService(kIOServiceCID, pNetService);
return v.ToNewCString();
}
ret = uri->QueryInterface(nsIURI::GetIID(), (void**)&url);
nsServiceManager::ReleaseService(kIOServiceCID, pNetService);
#endif // NECKO
if (NS_FAILED(ret)) {
printf("cannot create URL\n");
return v.ToNewCString();
}
/* create a bundle for the localization */
nsIStringBundleService* pStringService = nsnull;
ret = nsServiceManager::GetService(kStringBundleServiceCID,
kIStringBundleServiceIID, (nsISupports**) &pStringService);
if (NS_FAILED(ret)) {
printf("cannot get string service\n");
return v.ToNewCString();
}
nsILocale* locale = nsnull;
nsIStringBundle* bundle = nsnull;
#if 1
#ifndef NECKO
const char* spec = nsnull;
#else
char* spec = nsnull;
#endif /* NECKO */
ret = url->GetSpec(&spec);
if (NS_FAILED(ret)) {
printf("cannot get url spec\n");
nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService);
#ifdef NECKO
nsCRT::free(spec);
#endif /* NECKO */
return v.ToNewCString();
}
ret = pStringService->CreateBundle(spec, locale, &bundle);
#ifdef NECKO
nsCRT::free(spec);
#endif /* NECKO */
#else
ret = pStringService->CreateBundle(url, locale, &bundle);
#endif
if (NS_FAILED(ret)) {
printf("cannot create instance\n");
nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService);
return v.ToNewCString();
}
nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService);
/* localize the given string */
#if 1
nsString strtmp(genericString);
const PRUnichar *ptrtmp = strtmp.GetUnicode();
PRUnichar *ptrv = nsnull;
ret = bundle->GetStringFromName(ptrtmp, &ptrv);
v = ptrv;
#else
ret = bundle->GetStringFromName(nsString(genericString), v);
#endif
NS_RELEASE(bundle);
if (NS_FAILED(ret)) {
printf("cannot get string from name\n");
return v.ToNewCString();
}
return v.ToNewCString();
}
/**********************/
/* Modal dialog boxes */
/**********************/
PUBLIC PRBool
Wallet_Confirm(char * szMessage)
{
#ifdef NECKO
PRBool retval = PR_TRUE; /* default value */
nsresult res;
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res);
if (NS_FAILED(res)) {
return retval;
}
const nsString message = szMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
res = dialog->Confirm(message.GetUnicode(), &retval);
if (NS_FAILED(res)) {
return retval;
}
return retval;
#else
PRBool retval = PR_TRUE; /* default value */
nsINetSupportDialogService* dialog = NULL;
nsresult res = nsServiceManager::GetService(kNetSupportDialogCID,
nsINetSupportDialogService::GetIID(), (nsISupports**)&dialog);
if (NS_FAILED(res)) {
return retval;
}
if (dialog) {
const nsString message = szMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
dialog->Confirm(message, &retval);
}
nsServiceManager::ReleaseService(kNetSupportDialogCID, dialog);
return retval;
#endif
}
PUBLIC PRBool
Wallet_ConfirmYN(char * szMessage)
{
#ifdef NECKO
PRBool retval = PR_TRUE; /* default value */
nsresult res;
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res);
if (NS_FAILED(res)) {
return retval;
}
const nsString message = szMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
res = dialog->ConfirmYN(message.GetUnicode(), &retval);
if (NS_FAILED(res)) {
return retval;
}
return retval;
#else
PRBool retval = PR_TRUE; /* default value */
nsINetSupportDialogService* dialog = NULL;
nsresult res = nsServiceManager::GetService(kNetSupportDialogCID,
nsINetSupportDialogService::GetIID(), (nsISupports**)&dialog);
if (NS_FAILED(res)) {
return retval;
}
if (dialog) {
const nsString message = szMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
dialog->ConfirmYN(message, &retval);
}
nsServiceManager::ReleaseService(kNetSupportDialogCID, dialog);
return retval;
#endif
}
PUBLIC void
Wallet_Alert(char * szMessage)
{
#ifdef NECKO
nsresult res;
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res);
if (NS_FAILED(res)) {
return; // XXX should return the error
}
const nsString message = szMessage;
res = dialog->Alert(message.GetUnicode());
return; // XXX should return the error
#else
nsINetSupportDialogService* dialog = NULL;
nsresult res = nsServiceManager::GetService(kNetSupportDialogCID,
nsINetSupportDialogService::GetIID(), (nsISupports**)&dialog);
if (NS_FAILED(res)) {
return;
}
if (dialog) {
const nsString message = szMessage;
dialog->Alert(message);
}
nsServiceManager::ReleaseService(kNetSupportDialogCID, dialog);
return;
#endif
}
PUBLIC PRBool
Wallet_CheckConfirmYN(char * szMessage, char * szCheckMessage, PRBool* checkValue)
{
#ifdef NECKO
PRBool retval = PR_TRUE; /* default value */
nsresult res;
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res);
if (NS_FAILED(res)) {
*checkValue = 0;
return retval;
}
const nsString message = szMessage;
const nsString checkMessage = szCheckMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
res = dialog->ConfirmCheckYN(message.GetUnicode(), checkMessage.GetUnicode(), checkValue, &retval);
if (NS_FAILED(res)) {
*checkValue = 0;
}
if (*checkValue!=0 && *checkValue!=1) {
*checkValue = 0; /* this should never happen but it is happening!!! */
}
return retval;
#else
PRBool retval = PR_TRUE; /* default value */
nsINetSupportDialogService* dialog = NULL;
nsresult res = nsServiceManager::GetService(kNetSupportDialogCID,
nsINetSupportDialogService::GetIID(), (nsISupports**)&dialog);
if (NS_FAILED(res)) {
return retval;
}
if (dialog) {
const nsString message = szMessage;
const nsString checkMessage = szCheckMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
dialog->ConfirmCheckYN(message, checkMessage, &retval, checkValue);
if (*checkValue!=0 && *checkValue!=1) {
*checkValue = 0; /* this should never happen but it is happening!!! */
}
}
nsServiceManager::ReleaseService(kNetSupportDialogCID, dialog);
return retval;
#endif
}
char * wallet_GetString(char * szMessage)
{
#ifdef NECKO
nsString password;
PRBool retval;
nsresult res;
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res);
if (NS_FAILED(res)) {
return NULL; // XXX should return the error
}
const nsString message = szMessage;
PRUnichar* pwd;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
res = dialog->PromptPassword(message.GetUnicode(), &pwd, &retval);
if (NS_FAILED(res)) {
return NULL;
}
password = pwd;
delete[] pwd;
if (retval) {
return password.ToNewCString();
} else {
return NULL; /* user pressed cancel */
}
#else
nsString password;
PRBool retval;
nsINetSupportDialogService* dialog = NULL;
nsresult res = nsServiceManager::GetService(kNetSupportDialogCID,
nsINetSupportDialogService::GetIID(), (nsISupports**)&dialog);
if (NS_FAILED(res)) {
return NULL; /* failure value */
}
if (dialog) {
const nsString message = szMessage;
retval = PR_FALSE; /* in case user exits dialog by clicking X */
dialog->PromptPassword(message, password, &retval);
}
nsServiceManager::ReleaseService(kNetSupportDialogCID, dialog);
if (retval) {
return password.ToNewCString();
} else {
return NULL; /* user pressed cancel */
}
#endif
}
/**********************************************************************************/
/* The following routines are for locking the data base. They are not being used */
/**********************************************************************************/
#ifdef junk
//#include "prpriv.h" /* for NewNamedMonitor */
static PRMonitor * wallet_lock_monitor = NULL;
static PRThread * wallet_lock_owner = NULL;
static int wallet_lock_count = 0;
PRIVATE void
wallet_lock(void) {
if(!wallet_lock_monitor) {
// wallet_lock_monitor =
// PR_NewNamedMonitor("wallet-lock");
}
PR_EnterMonitor(wallet_lock_monitor);
while(PR_TRUE) {
/* no current owner or owned by this thread */
PRThread * t = PR_CurrentThread();
if(wallet_lock_owner == NULL || wallet_lock_owner == t) {
wallet_lock_owner = t;
wallet_lock_count++;
PR_ExitMonitor(wallet_lock_monitor);
return;
}
/* owned by someone else -- wait till we can get it */
PR_Wait(wallet_lock_monitor, PR_INTERVAL_NO_TIMEOUT);
}
}
PRIVATE void
wallet_unlock(void) {
PR_EnterMonitor(wallet_lock_monitor);
#ifdef DEBUG
/* make sure someone doesn't try to free a lock they don't own */
PR_ASSERT(wallet_lock_owner == PR_CurrentThread());
#endif
wallet_lock_count--;
if(wallet_lock_count == 0) {
wallet_lock_owner = NULL;
PR_Notify(wallet_lock_monitor);
}
PR_ExitMonitor(wallet_lock_monitor);
}
#endif
/**********************************************************/
/* The following routines are for accessing the data base */
/**********************************************************/
/*
* clear out the designated list
*/
void
wallet_Clear(nsVoidArray ** list) {
wallet_MapElement * ptr;
PRInt32 count = LIST_COUNT((*list));
for (PRInt32 i=count-1; i>=0; i--) {
ptr = NS_STATIC_CAST(wallet_MapElement*, (*list)->ElementAt(i));
delete ptr->item1;
delete ptr->item2;
wallet_Sublist * ptr1;
PRInt32 count = LIST_COUNT(ptr->itemList);
for (PRInt32 i=0; i<count; i++) {
ptr1 = NS_STATIC_CAST(wallet_Sublist*, ptr->itemList->ElementAt(i));
delete ptr1->item;
}
delete ptr->itemList;
(*list)->RemoveElement(ptr);
delete ptr;
}
*list = 0;
}
/*
* add an entry to the designated list
*/
void
wallet_WriteToList(
nsAutoString& item1,
nsAutoString& item2,
nsVoidArray* itemList,
nsVoidArray*& list,
PlacementType placement = DUP_BEFORE) {
wallet_MapElement * ptr;
PRBool added_to_list = PR_FALSE;
wallet_MapElement * mapElement;
mapElement = PR_NEW(wallet_MapElement);
mapElement->item1 = &item1;
mapElement->item2 = &item2;
mapElement->itemList = itemList;
/* make sure the list exists */
if(!list) {
list = new nsVoidArray();
if(!list) {
return;
}
}
/*
* Add new entry to the list in alphabetical order by item1.
* If identical value of item1 exists, use "placement" parameter to
* determine what to do
*/
item1.ToLowerCase();
if (AT_END==placement) {
list->AppendElement(mapElement);
return;
}
PRInt32 count = LIST_COUNT(list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_MapElement*, list->ElementAt(i));
if((ptr->item1->Compare(item1))==0) {
if (DUP_OVERWRITE==placement) {
delete ptr->item1;
delete ptr->item2;
delete mapElement;
ptr->item1 = &item1;
ptr->item2 = &item2;
} else if (DUP_BEFORE==placement) {
list->InsertElementAt(mapElement, i);
}
if (DUP_AFTER!=placement) {
added_to_list = PR_TRUE;
break;
}
} else if((ptr->item1->Compare(item1))>=0) {
list->InsertElementAt(mapElement, i);
added_to_list = PR_TRUE;
break;
}
}
if (!added_to_list) {
list->AppendElement(mapElement);
}
}
/*
* fetch an entry from the designated list
*/
PRBool
wallet_ReadFromList(
nsAutoString item1,
nsAutoString& item2,
nsVoidArray*& itemList,
nsVoidArray*& list,
PRInt32& index)
{
if (!list || (index == -1)) {
return PR_FALSE;
}
/* find item1 in the list */
wallet_MapElement * ptr;
item1.ToLowerCase();
PRInt32 count = LIST_COUNT(list);
for (PRInt32 i=index; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_MapElement*, list->ElementAt(i));
if((ptr->item1->Compare(item1))==0) {
item2 = nsAutoString(*ptr->item2);
itemList = ptr->itemList;
index = i+1;
if (index == count) {
index = -1;
}
return PR_TRUE;
}
}
index = 0;
return PR_FALSE;
}
PRBool
wallet_ReadFromList(
nsAutoString item1,
nsAutoString& item2,
nsVoidArray*& itemList,
nsVoidArray*& list)
{
PRInt32 index = 0;
return wallet_ReadFromList(item1, item2, itemList, list, index);
}
/************************************************************/
/* The following routines are for unlocking the stored data */
/************************************************************/
#define maxKeySize 100
char key[maxKeySize+1];
PRUint32 keyPosition = 0;
PRBool keyCancel = PR_FALSE;
PRBool keySet = PR_FALSE;
PUBLIC void
Wallet_RestartKey() {
keyPosition = 0;
}
PUBLIC char
Wallet_GetKey() {
if (keyPosition >= PL_strlen(key)) {
keyPosition = 0;
}
return key[keyPosition++];
}
PUBLIC PRBool
Wallet_KeySet() {
return keySet;
}
PUBLIC PRBool
Wallet_CancelKey() {
return keyCancel;
}
PUBLIC nsresult Wallet_ProfileDirectory(nsFileSpec& dirSpec) {
/* return the profile */
nsIFileSpec* spec =
NS_LocateFileOrDirectory(nsSpecialFileSpec::App_UserProfileDirectory50);
if (!spec) {
return NS_ERROR_FAILURE;
}
return spec->GetFileSpec(&dirSpec);
}
PUBLIC nsresult Wallet_ResourceDirectory(nsFileSpec& dirSpec) {
nsIFileSpec* spec =
NS_LocateFileOrDirectory(nsSpecialFileSpec::App_ResDirectory);
if (!spec) {
return NS_ERROR_FAILURE;
}
return spec->GetFileSpec(&dirSpec);
}
/* returns -1 if key does not exist, 0 if key is of length 0, 1 otherwise */
PRIVATE PRInt32
wallet_KeySize() {
nsFileSpec dirSpec;
nsresult rv = Wallet_ProfileDirectory(dirSpec);
if (NS_FAILED(rv)) {
return -1;
}
nsInputFileStream strm(dirSpec + "key");
if (!strm.is_open()) {
return -1;
} else {
char c = strm.get();
PRInt32 rv = (strm.eof() ? 0 : 1);
strm.close();
return rv;
}
}
PUBLIC PRBool
Wallet_SetKey(PRBool isNewkey) {
if (Wallet_KeySet() && !isNewkey) {
return PR_TRUE;
}
Wallet_RestartKey();
/* ask the user for his key */
char * password;
if (wallet_KeySize() < 0) { /* no password has yet been established */
password = Wallet_Localize("firstPassword");
} else if (isNewkey) {
password = Wallet_Localize("newPassword");
} else {
password = Wallet_Localize("password");
}
char * newkey;
if ((wallet_KeySize() == 0) && !isNewkey) {
newkey = PL_strdup("");
} else {
newkey = wallet_GetString(password);
}
keyCancel = PR_FALSE;
if (newkey == NULL) { /* user hit cancel button */
if (wallet_KeySize() < 0) { /* no password file existed before */
newkey = PL_strdup(""); /* use zero-length password */
} else if (isNewkey) { /* user is changing the password */
newkey = PL_strdup(""); /* use zero-length password */
} else {
keyCancel = PR_TRUE;
return PR_FALSE; /* user could not supply the correct password */
}
}
PR_FREEIF(password);
for (; (keyPosition < PL_strlen(newkey) && keyPosition < maxKeySize); keyPosition++) {
key[keyPosition] = newkey[keyPosition];
}
key[keyPosition] = '\0';
PR_FREEIF(newkey);
Wallet_RestartKey();
/* verify this with the saved key */
if (isNewkey || (wallet_KeySize() < 0)) {
/*
* Either key is to be changed or the file containing the saved key doesn' exist.
* In either case we need to (re)create and re(write) the file.
*/
nsFileSpec dirSpec;
nsresult rval = Wallet_ProfileDirectory(dirSpec);
if (NS_FAILED(rval)) {
return PR_FALSE;
}
nsOutputFileStream strm2(dirSpec + "key");
if (!strm2.is_open()) {
*key = '\0';
return PR_FALSE;
}
/* If we store the key obscured by the key itself, then the result will be zero
* for all keys (since we are using XOR to obscure). So instead we store
* key[1..n],key[0] obscured by the actual key.
*/
if (PL_strlen(key) != 0) {
char* p = key+1;
while (*p) {
strm2.put(*(p++)^Wallet_GetKey());
}
strm2.put((*key)^Wallet_GetKey());
}
strm2.flush();
strm2.close();
Wallet_RestartKey();
keySet = PR_TRUE;
return PR_TRUE;
} else {
/* file of saved key existed so see if it matches the key the user typed in */
/*
* Note that eof() is not set until after we read past the end of the file. That
* is why the following code reads a character and immediately after the read
* checks for eof()
*/
/* test for a null key */
if ((PL_strlen(key) == 0) && (wallet_KeySize() == 0) ) {
Wallet_RestartKey();
keySet = PR_TRUE;
return PR_TRUE;
}
nsFileSpec dirSpec;
nsresult rval = Wallet_ProfileDirectory(dirSpec);
if (NS_FAILED(rval)) {
return PR_FALSE;
}
nsInputFileStream strm(dirSpec + "key");
Wallet_RestartKey();
char* p = key+1;
while (*p) {
if (strm.get() != (*(p++)^Wallet_GetKey()) || strm.eof()) {
strm.close();
*key = '\0';
return PR_FALSE;
}
}
if (strm.get() != ((*key)^Wallet_GetKey()) || strm.eof()) {
strm.close();
*key = '\0';
return PR_FALSE;
}
strm.get(); /* to get past the end of the file so eof() will get set */
PRBool rv = strm.eof();
strm.close();
if (rv) {
Wallet_RestartKey();
keySet = PR_TRUE;
return PR_TRUE;
} else {
*key = '\0';
return PR_FALSE;
}
}
}
/******************************************************/
/* The following routines are for accessing the files */
/******************************************************/
/*
* get a line from a file
* return -1 if end of file reached
* strip carriage returns and line feeds from end of line
*/
PRInt32
wallet_GetLine(nsInputFileStream strm, nsAutoString*& aLine, PRBool obscure) {
/* read the line */
aLine = new nsAutoString("");
if (!aLine) {
return NS_ERROR_OUT_OF_MEMORY;
}
char c;
for (;;) {
c = strm.get()^(obscure ? Wallet_GetKey() : (char)0);
if (c == '\n') {
break;
}
/* note that eof is not set until we read past the end of the file */
if (strm.eof()) {
return -1;
}
if (c != '\r') {
*aLine += c;
}
}
return NS_OK;
}
/*
* Write a line to a file
* return -1 if an error occurs
*/
PRInt32
wallet_PutLine(nsOutputFileStream strm, const nsString& aLine, PRBool obscure)
{
/* allocate a buffer from the heap */
char * cp = new char[aLine.Length() + 1];
if (! cp) {
return NS_ERROR_OUT_OF_MEMORY;
}
aLine.ToCString(cp, aLine.Length() + 1);
/* output each character */
char* p = cp;
while (*p) {
strm.put(*(p++)^(obscure ? Wallet_GetKey() : (char)0));
}
strm.put('\n'^(obscure ? Wallet_GetKey() : (char)0));
delete[] cp;
return 0;
}
/*
* write contents of designated list into designated file
*/
void
wallet_WriteToFile(char* filename, nsVoidArray* list, PRBool obscure) {
wallet_MapElement * ptr;
if (obscure && !Wallet_KeySet()) {
return;
}
/* open output stream */
nsFileSpec dirSpec;
nsresult rv = Wallet_ProfileDirectory(dirSpec);
if (NS_FAILED(rv)) {
return;
}
nsOutputFileStream strm(dirSpec + filename);
if (!strm.is_open()) {
NS_ERROR("unable to open file");
return;
}
/* make sure the list exists */
if(!list) {
return;
}
Wallet_RestartKey();
/* traverse the list */
PRInt32 count = LIST_COUNT(list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_MapElement*, list->ElementAt(i));
if (NS_FAILED(wallet_PutLine(strm, *ptr->item1, obscure))) {
break;
}
if (*ptr->item2 != "") {
if (NS_FAILED(wallet_PutLine(strm, *ptr->item2, obscure))) {
break;
}
} else {
wallet_Sublist * ptr1;
PRInt32 count = LIST_COUNT(ptr->itemList);
for (PRInt32 i=0; i<count; i++) {
ptr1 = NS_STATIC_CAST(wallet_Sublist*, ptr->itemList->ElementAt(i));
if (NS_FAILED(wallet_PutLine(strm, *ptr->item1, obscure))) {
break;
}
}
}
if (NS_FAILED(wallet_PutLine(strm, "", obscure))) {
break;
}
}
/* close the stream */
strm.flush();
strm.close();
}
/*
* Read contents of designated file into designated list
*/
void
wallet_ReadFromFile
(char* filename, nsVoidArray*& list, PRBool obscure, PRBool localFile, PlacementType placement = DUP_AFTER) {
/* open input stream */
nsFileSpec dirSpec;
nsresult rv;
if (localFile) {
rv = Wallet_ProfileDirectory(dirSpec);
} else {
rv = Wallet_ResourceDirectory(dirSpec);
}
if (NS_FAILED(rv)) {
return;
}
nsInputFileStream strm(dirSpec + filename);
if (!strm.is_open()) {
/* file doesn't exist -- that's not an error */
return;
}
Wallet_RestartKey();
for (;;) {
nsAutoString * aItem1;
if (NS_FAILED(wallet_GetLine(strm, aItem1, obscure))) {
/* end of file reached */
strm.close();
return;
}
nsAutoString * aItem2;
if (NS_FAILED(wallet_GetLine(strm, aItem2, obscure))) {
/* unexpected end of file reached */
delete aItem1;
strm.close();
return;
}
nsAutoString * aItem3;
if (NS_FAILED(wallet_GetLine(strm, aItem3, obscure))) {
/* end of file reached */
nsVoidArray* dummy = NULL;
wallet_WriteToList(*aItem1, *aItem2, dummy, list, placement);
strm.close();
return;
}
if (aItem3->Length()==0) {
/* just a pair of values, no need for a sublist */
nsVoidArray* dummy = NULL;
wallet_WriteToList(*aItem1, *aItem2, dummy, list, placement);
} else {
/* need to create a sublist and put item2 and item3 onto it */
nsVoidArray * itemList = new nsVoidArray();
wallet_Sublist * sublist;
sublist = PR_NEW(wallet_Sublist);
sublist->item = new nsAutoString (*aItem2);
itemList->AppendElement(sublist);
delete aItem2;
sublist = PR_NEW(wallet_Sublist);
sublist->item = new nsAutoString (*aItem3);
itemList->AppendElement(sublist);
delete aItem3;
/* add any following items to sublist up to next blank line */
nsAutoString * dummy2 = new nsAutoString("");
if (!dummy2) {
strm.close();
return;
}
for (;;) {
/* get next item for sublist */
if (NS_FAILED(wallet_GetLine(strm, aItem3, obscure))) {
/* end of file reached */
wallet_WriteToList(*aItem1, *dummy2, itemList, list, placement);
strm.close();
return;
}
if (aItem3->Length()==0) {
/* blank line reached indicating end of sublist */
wallet_WriteToList(*aItem1, *dummy2, itemList, list, placement);
break;
}
/* add item to sublist */
sublist = PR_NEW(wallet_Sublist);
sublist->item = new nsAutoString (*aItem3);
itemList->AppendElement(sublist);
delete aItem3;
}
}
}
}
/*
* Read contents of designated URLFieldToSchema file into designated list
*/
void
wallet_ReadFromURLFieldToSchemaFile
(char* filename, nsVoidArray*& list, PlacementType placement = DUP_AFTER) {
/* open input stream */
nsFileSpec dirSpec;
nsresult rv = Wallet_ResourceDirectory(dirSpec);
if (NS_FAILED(rv)) {
return;
}
nsInputFileStream strm(dirSpec + filename);
if (!strm.is_open()) {
/* file doesn't exist -- that's not an error */
return;
}
/* Wallet_RestartKey(); not needed since file is not encoded */
/* make sure the list exists */
if(!list) {
list = new nsVoidArray();
if(!list) {
strm.close();
return;
}
}
for (;;) {
nsAutoString * aItem;
if (NS_FAILED(wallet_GetLine(strm, aItem, PR_FALSE))) {
/* end of file reached */
strm.close();
return;
}
nsVoidArray * itemList = new nsVoidArray();
nsAutoString * dummy = new nsAutoString("");
if (!dummy) {
strm.close();
return;
}
wallet_WriteToList(*aItem, *dummy, itemList, list, placement);
for (;;) {
nsAutoString * aItem1;
if (NS_FAILED(wallet_GetLine(strm, aItem1, PR_FALSE))) {
/* end of file reached */
strm.close();
return;
}
if (aItem1->Length()==0) {
/* end of url reached */
break;
}
nsAutoString * aItem2;
if (NS_FAILED(wallet_GetLine(strm, aItem2, PR_FALSE))) {
/* unexpected end of file reached */
delete aItem1;
strm.close();
return;
}
nsVoidArray* dummy = NULL;
wallet_WriteToList(*aItem1, *aItem2, dummy, itemList, placement);
nsAutoString * aItem3;
if (NS_FAILED(wallet_GetLine(strm, aItem3, PR_FALSE))) {
/* end of file reached */
strm.close();
return;
}
if (aItem3->Length()!=0) {
/* invalid file format */
strm.close();
delete aItem3;
return;
}
delete aItem3;
}
}
}
/*********************************************************************/
/* The following are utility routines for the main wallet processing */
/*********************************************************************/
/*
* given a field name, get the value
*/
PRInt32 FieldToValue(
nsAutoString field,
nsAutoString& schema,
nsAutoString& value,
nsVoidArray*& itemList,
PRInt32& index)
{
/* return if no SchemaToValue list exists */
if (!wallet_SchemaToValue_list) {
return -1;
}
/* if no schema name is given, fetch schema name from field/schema tables */
nsVoidArray* dummy;
if (index == -1) {
index = 0;
}
if ((schema.Length() > 0) ||
wallet_ReadFromList(field, schema, dummy, wallet_specificURLFieldToSchema_list) ||
wallet_ReadFromList(field, schema, dummy, wallet_FieldToSchema_list)) {
/* schema name found, now fetch value from schema/value table */
PRInt32 index2 = index;
if (wallet_ReadFromList(schema, value, itemList, wallet_SchemaToValue_list, index2)) {
/* value found, prefill it into form */
index = index2;
return 0;
} else {
/* value not found, see if concatenation rule exists */
nsVoidArray * itemList2;
nsAutoString dummy2;
if (wallet_ReadFromList(schema, dummy2, itemList2, wallet_SchemaConcat_list)) {
/* concatenation rules exist, generate value as a concatenation */
wallet_Sublist * ptr1;
value = nsAutoString("");
nsAutoString value2;
PRInt32 count = LIST_COUNT(itemList2);
for (PRInt32 i=0; i<count; i++) {
ptr1 = NS_STATIC_CAST(wallet_Sublist*, itemList2->ElementAt(i));
if (wallet_ReadFromList(*(ptr1->item), value2, dummy, wallet_SchemaToValue_list)) {
if (value.Length()>0) {
value += " ";
}
value += value2;
}
}
index = -1;
itemList = nsnull;
if (value.Length()>0) {
return 0;
}
}
}
} else {
/* schema name not found, use field name as schema name and fetch value */
PRInt32 index2 = index;
if (wallet_ReadFromList(field, value, itemList, wallet_SchemaToValue_list, index2)) {
/* value found, prefill it into form */
schema = nsAutoString(field);
index = index2;
return 0;
}
}
index = -1;
return -1;
}
PRInt32
wallet_GetSelectIndex(
nsIDOMHTMLSelectElement* selectElement,
nsAutoString value,
PRInt32& index)
{
nsresult result;
PRUint32 length;
selectElement->GetLength(&length);
nsIDOMHTMLCollection * options;
result = selectElement->GetOptions(&options);
if ((NS_SUCCEEDED(result)) && (nsnull != options)) {
PRUint32 numOptions;
options->GetLength(&numOptions);
for (PRUint32 optionX = 0; optionX < numOptions; optionX++) {
nsIDOMNode* optionNode = nsnull;
options->Item(optionX, &optionNode);
if (nsnull != optionNode) {
nsIDOMHTMLOptionElement* optionElement = nsnull;
result = optionNode->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&optionElement);
if ((NS_SUCCEEDED(result)) && (nsnull != optionElement)) {
nsAutoString optionValue;
nsAutoString optionText;
optionElement->GetValue(optionValue);
optionElement->GetText(optionText);
if (value==optionValue || value==optionText) {
index = optionX;
return 0;
}
NS_RELEASE(optionElement);
}
NS_RELEASE(optionNode);
}
}
NS_RELEASE(options);
}
return -1;
}
PRInt32
wallet_GetPrefills(
nsIDOMNode* elementNode,
nsIDOMHTMLInputElement*& inputElement,
nsIDOMHTMLSelectElement*& selectElement,
nsAutoString*& schemaPtr,
nsAutoString*& valuePtr,
PRInt32& selectIndex,
PRInt32& index)
{
nsresult result;
/* get prefills for input element */
result = elementNode->QueryInterface(kIDOMHTMLInputElementIID, (void**)&inputElement);
if ((NS_SUCCEEDED(result)) && (nsnull != inputElement)) {
nsAutoString type;
result = inputElement->GetType(type);
if ((NS_SUCCEEDED(result)) && ((type =="") || (type.Compare("text", PR_TRUE) == 0))) {
nsAutoString field;
result = inputElement->GetName(field);
if (NS_SUCCEEDED(result)) {
nsAutoString schema("");
nsAutoString value;
nsVoidArray* itemList;
/* get schema name from vcard attribute if it exists */
nsIDOMElement * element;
result = elementNode->QueryInterface(kIDOMElementIID, (void**)&element);
if ((NS_SUCCEEDED(result)) && (nsnull != element)) {
nsAutoString vcard("VCARD_NAME");
result = element->GetAttribute(vcard, schema);
NS_RELEASE(element);
}
/*
* if schema name was specified in vcard attribute then get value from schema name,
* otherwise get value from field name by using mapping tables to get schema name
*/
if (FieldToValue(field, schema, value, itemList, index) == 0) {
if (value == "" && nsnull != itemList) {
/* pick first of a set of synonymous values */
value = *(((wallet_Sublist *)itemList->ElementAt(0))->item);
}
valuePtr = new nsAutoString(value);
schemaPtr = new nsAutoString(schema);
selectElement = nsnull;
selectIndex = -1;
return NS_OK;
}
}
}
NS_RELEASE(inputElement);
return -1;
}
/* get prefills for dropdown list */
result = elementNode->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&selectElement);
if ((NS_SUCCEEDED(result)) && (nsnull != selectElement)) {
nsAutoString field;
result = selectElement->GetName(field);
if (NS_SUCCEEDED(result)) {
nsAutoString schema("");
nsAutoString value;
nsVoidArray* itemList;
if (FieldToValue(field, schema, value, itemList, index) == 0) {
if (value != "") {
/* no synonym list, just one value to try */
result = wallet_GetSelectIndex(selectElement, value, selectIndex);
if (NS_SUCCEEDED(result)) {
/* value matched one of the values in the drop-down list */
valuePtr = new nsAutoString(value);
schemaPtr = new nsAutoString(schema);
inputElement = nsnull;
return NS_OK;
}
} else {
/* synonym list exists, try each value */
for (PRInt32 i=0; i<LIST_COUNT(itemList); i++) {
value = *(((wallet_Sublist *)itemList->ElementAt(i))->item);
result = wallet_GetSelectIndex(selectElement, value, selectIndex);
if (NS_SUCCEEDED(result)) {
/* value matched one of the values in the drop-down list */
valuePtr = new nsAutoString(value);
schemaPtr = new nsAutoString(schema);
inputElement = nsnull;
return NS_OK;
}
}
}
}
}
NS_RELEASE(selectElement);
}
return -1;
}
/*
* initialization for wallet session (done only once)
*/
void
wallet_Initialize() {
static PRBool wallet_Initialized = PR_FALSE;
static PRBool wallet_keyInitialized = PR_FALSE;
if (!wallet_Initialized) {
wallet_ReadFromFile("FieldSchema.tbl", wallet_FieldToSchema_list, PR_FALSE, PR_FALSE);
wallet_ReadFromURLFieldToSchemaFile("URLFieldSchema.tbl", wallet_URLFieldToSchema_list);
wallet_ReadFromFile("SchemaConcat.tbl", wallet_SchemaConcat_list, PR_FALSE, PR_FALSE);
wallet_Initialized = PR_TRUE;
}
if (!wallet_keyInitialized) {
Wallet_RestartKey();
char * message = Wallet_Localize("IncorrectKey_TryAgain?");
while (!Wallet_SetKey(PR_FALSE)) {
if (Wallet_CancelKey() || !Wallet_Confirm(message)) {
PR_FREEIF(message);
return;
}
}
PR_FREEIF(message);
wallet_ReadFromFile("SchemaValue.tbl", wallet_SchemaToValue_list, PR_TRUE, PR_TRUE);
wallet_keyInitialized = PR_TRUE;
}
#if DEBUG
// fprintf(stdout,"Field to Schema table \n");
// wallet_Dump(wallet_FieldToSchema_list);
// fprintf(stdout,"SchemaConcat table \n");
// wallet_Dump(wallet_SchemaConcat_list);
// fprintf(stdout,"URL Field to Schema table \n");
// char item1[100];
// wallet_MapElement * ptr;
// PRInt32 count = LIST_COUNT(wallet_URLFieldToSchema_list);
// for (PRInt32 i=0; i<count; i++) {
// ptr = NS_STATIC_CAST(wallet_MapElement*, wallet_URLFieldToSchema_list->ElementAt(i));
// ptr->item1->ToCString(item1, 100);
// fprintf(stdout, item1);
// fprintf(stdout,"\n");
// wallet_Dump(ptr->itemList);
// }
// fprintf(stdout,"Schema to Value table \n");
// wallet_Dump(wallet_SchemaToValue_list);
#endif
}
#ifdef SingleSignon
extern int SI_SaveSignonData();
extern int SI_LoadSignonData(PRBool fullLoad);
#endif
PUBLIC
void WLLT_ChangePassword() {
/* do nothing if password was never set */
if (wallet_KeySize() < 0) {
return;
}
/* read in user data using old key */
wallet_Initialize();
#ifdef SingleSignon
SI_LoadSignonData(PR_TRUE);
#endif
if (!Wallet_KeySet()) {
return;
}
/* establish new key */
Wallet_SetKey(PR_TRUE);
/* write out user data using new key */
wallet_WriteToFile("SchemaValue.tbl", wallet_SchemaToValue_list, PR_TRUE);
#ifdef SingleSignon
SI_SaveSignonData();
#endif
}
void
wallet_InitializeURLList() {
static PRBool wallet_URLListInitialized = PR_FALSE;
if (!wallet_URLListInitialized) {
wallet_ReadFromFile("URL.tbl", wallet_URL_list, PR_FALSE, PR_TRUE);
wallet_URLListInitialized = PR_TRUE;
}
}
/*
* initialization for current URL
*/
void
wallet_InitializeCurrentURL(nsIDocument * doc) {
static nsIURI * lastUrl = NULL;
/* get url */
nsIURI* url;
url = doc->GetDocumentURL();
if (lastUrl == url) {
NS_RELEASE(url);
return;
} else {
if (lastUrl) {
//?? NS_RELEASE(lastUrl);
}
lastUrl = url;
}
/* get host+file */
#ifdef NECKO
char* host;
#else
const char* host;
#endif
nsresult rv = url->GetHost(&host);
if (NS_FAILED(rv)) {
return;
}
nsAutoString urlName = nsAutoString(host);
#ifdef NECKO
nsCRT::free(host);
#endif
#ifdef NECKO
char* file;
url->GetPath(&file);
#else
const char* file;
url->GetFile(&file);
#endif
urlName = urlName + file;
#ifdef NECKO
nsCRT::free(file);
#endif
NS_RELEASE(url);
/* get field/schema mapping specific to current url */
wallet_MapElement * ptr;
PRInt32 count = LIST_COUNT(wallet_URLFieldToSchema_list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_MapElement*, wallet_URLFieldToSchema_list->ElementAt(i));
if (*(ptr->item1) == urlName) {
wallet_specificURLFieldToSchema_list = ptr->itemList;
break;
}
}
#ifdef DEBUG
// fprintf(stdout,"specific URL Field to Schema table \n");
// wallet_Dump(wallet_specificURLFieldToSchema_list);
#endif
}
#define SEPARATOR "#*%$"
nsAutoString *
wallet_GetNextInString(char*& ptr) {
nsAutoString * result;
char * endptr;
endptr = PL_strstr(ptr, SEPARATOR);
if (!endptr) {
return NULL;
}
*endptr = '\0';
result = new nsAutoString(ptr);
*endptr = SEPARATOR[0];
ptr = endptr + PL_strlen(SEPARATOR);
return result;
}
void
wallet_ReleasePrefillElementList(nsVoidArray * wallet_PrefillElement_list) {
if (wallet_PrefillElement_list) {
wallet_PrefillElement * ptr;
PRInt32 count = LIST_COUNT(wallet_PrefillElement_list);
for (PRInt32 i=count-1; i>=0; i--) {
ptr = NS_STATIC_CAST(wallet_PrefillElement*, wallet_PrefillElement_list->ElementAt(i));
if (ptr->inputElement) {
NS_RELEASE(ptr->inputElement);
} else {
NS_RELEASE(ptr->selectElement);
}
delete ptr->schema;
delete ptr->value;
wallet_PrefillElement_list->RemoveElement(ptr);
delete ptr;
}
}
}
#define BUFLEN3 5000
#define BREAK '\001'
nsVoidArray * wallet_list;
nsString wallet_url;
PUBLIC void
WLLT_GetPrefillListForViewer(nsString& aPrefillList)
{
char *buffer = (char*)PR_Malloc(BUFLEN3);
int g = 0, prefillNum = 0;
wallet_PrefillElement * ptr;
buffer[0] = '\0';
char * schema;
char * value;
PRInt32 count = LIST_COUNT(wallet_list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_PrefillElement*, wallet_list->ElementAt(i));
schema = ptr->schema->ToNewCString();
value = ptr->value->ToNewCString();
g += PR_snprintf(buffer+g, BUFLEN3-g,
"%c%d%c%s%c%s",
BREAK, ptr->count,
BREAK, schema,
BREAK, value);
delete []schema;
delete []value;
}
char * urlCString;
urlCString = wallet_url.ToNewCString();
g += PR_snprintf(buffer+g, BUFLEN3-g,"%c%ld%c%s", BREAK, wallet_list, BREAK, urlCString);
delete []urlCString;
aPrefillList = buffer;
PR_FREEIF(buffer);
}
extern PRBool
SI_InSequence(char* sequence, int number);
extern char*
SI_FindValueInArgs(nsAutoString results, char* name);
PRIVATE void
wallet_FreeURL(wallet_MapElement *url) {
if(!url) {
return;
}
wallet_URL_list->RemoveElement(url);
PR_FREEIF(url->item1);
PR_FREEIF(url->item2);
PR_Free(url);
}
PUBLIC void
Wallet_SignonViewerReturn (nsAutoString results) {
wallet_MapElement *url;
char * gone;
/* step through all nopreviews and delete those that are in the sequence */
gone = SI_FindValueInArgs(results, "|goneP|");
PRInt32 count = LIST_COUNT(wallet_URL_list);
while (count>0) {
count--;
url = NS_STATIC_CAST(wallet_MapElement*, wallet_URL_list->ElementAt(count));
if (url && SI_InSequence(gone, count)) {
url->item2->SetCharAt('n', NO_PREVIEW);
if (url->item2->CharAt(NO_CAPTURE) == 'n') {
wallet_FreeURL(url);
wallet_WriteToFile("URL.tbl", wallet_URL_list, PR_FALSE);
}
}
}
delete[] gone;
/* step through all nocaptures and delete those that are in the sequence */
gone = SI_FindValueInArgs(results, "|goneC|");
PRInt32 count2 = LIST_COUNT(wallet_URL_list);
while (count2>0) {
count2--;
url = NS_STATIC_CAST(wallet_MapElement*, wallet_URL_list->ElementAt(count2));
if (url && SI_InSequence(gone, count)) {
url->item2->SetCharAt('n', NO_CAPTURE);
if (url->item2->CharAt(NO_PREVIEW) == 'n') {
wallet_FreeURL(url);
wallet_WriteToFile("URL.tbl", wallet_URL_list, PR_FALSE);
}
}
}
delete[] gone;
}
/*
* see if user wants to capture data on current page
*/
PRIVATE PRBool
wallet_OKToCapture(char* urlName) {
nsAutoString * url = new nsAutoString(urlName);
/* see if this url is already on list of url's for which we don't want to capture */
wallet_InitializeURLList();
nsVoidArray* dummy;
nsAutoString * value = new nsAutoString("nn");
if (!url || !value) {
return PR_FALSE;
}
if (wallet_ReadFromList(*url, *value, dummy, wallet_URL_list)) {
if (value->CharAt(NO_CAPTURE) == 'y') {
return PR_FALSE;
}
}
/* ask user if we should capture the values on this form */
char * message = Wallet_Localize("WantToCaptureForm?");
char * checkMessage = Wallet_Localize("NeverSave");
PRBool checkValue;
PRBool result = Wallet_CheckConfirmYN(message, checkMessage, &checkValue);
if (!result) {
if (checkValue) {
/* add URL to list with NO_CAPTURE indicator set */
value->SetCharAt('y', NO_CAPTURE);
wallet_WriteToList(*url, *value, dummy, wallet_URL_list, DUP_OVERWRITE);
wallet_WriteToFile("URL.tbl", wallet_URL_list, PR_FALSE);
} else {
delete url;
}
}
PR_FREEIF(checkMessage);
PR_FREEIF(message);
return result;
}
/*
* capture the value of a form element
*/
PRIVATE void
wallet_Capture(nsIDocument* doc, nsString field, nsString value, nsString vcard) {
/* do nothing if there is no value */
if (!value.Length()) {
return;
}
/* read in the mappings if they are not already present */
if (!vcard.Length()) {
wallet_Initialize();
wallet_InitializeCurrentURL(doc);
if (!Wallet_KeySet()) {
return;
}
}
nsAutoString oldValue;
/* is there a mapping from this field name to a schema name */
nsAutoString schema(vcard);
nsVoidArray* dummy;
if (schema.Length() ||
(wallet_ReadFromList(field, schema, dummy, wallet_specificURLFieldToSchema_list)) ||
(wallet_ReadFromList(field, schema, dummy, wallet_FieldToSchema_list))) {
/* field to schema mapping already exists */
/* is this a new value for the schema */
PRInt32 index = 0;
PRInt32 lastIndex = index;
while(wallet_ReadFromList(schema, oldValue, dummy, wallet_SchemaToValue_list, index)) {
if (oldValue == value) {
/*
* Remove entry from wallet_SchemaToValue_list and then reinsert. This will
* keep multiple values in that list for the same field ordered with
* most-recently-used first. That's useful since the first such entry
* is the default value used for pre-filling.
*/
wallet_MapElement * mapElement =
(wallet_MapElement *) (wallet_SchemaToValue_list->ElementAt(lastIndex));
wallet_SchemaToValue_list->RemoveElementAt(lastIndex);
wallet_WriteToList(
*(mapElement->item1),
*(mapElement->item2),
mapElement->itemList,
wallet_SchemaToValue_list);
delete mapElement;
return;
}
lastIndex = index;
}
/* this is a new value so store it */
nsAutoString * aValue = new nsAutoString(value);
nsAutoString * aSchema = new nsAutoString(schema);
dummy = 0;
wallet_WriteToList(*aSchema, *aValue, dummy, wallet_SchemaToValue_list);
wallet_WriteToFile("SchemaValue.tbl", wallet_SchemaToValue_list, PR_TRUE);
} else {
/* no field to schema mapping so assume schema name is same as field name */
/* is this a new value for the schema */
PRInt32 index = 0;
PRInt32 lastIndex = index;
while(wallet_ReadFromList(field, oldValue, dummy, wallet_SchemaToValue_list, index)) {
if (oldValue == value) {
/*
* Remove entry from wallet_SchemaToValue_list and then reinsert. This will
* keep multiple values in that list for the same field ordered with
* most-recently-used first. That's useful since the first such entry
* is the default value used for pre-filling.
*/
wallet_MapElement * mapElement =
(wallet_MapElement *) (wallet_SchemaToValue_list->ElementAt(lastIndex));
wallet_SchemaToValue_list->RemoveElementAt(lastIndex);
wallet_WriteToList(
*(mapElement->item1),
*(mapElement->item2),
mapElement->itemList,
wallet_SchemaToValue_list);
delete mapElement;
return;
}
lastIndex = index;
}
/* this is a new value so store it */
nsAutoString * aField = new nsAutoString(field);
nsAutoString * aValue = new nsAutoString(value);
dummy = 0;
wallet_WriteToList(*aField, *aValue, dummy, wallet_SchemaToValue_list);
wallet_WriteToFile("SchemaValue.tbl", wallet_SchemaToValue_list, PR_TRUE);
}
}
/***************************************************************/
/* The following are the interface routines seen by other dlls */
/***************************************************************/
#define BUFLEN2 5000
#define BREAK '\001'
PUBLIC void
WLLT_GetNopreviewListForViewer(nsString& aNopreviewList)
{
char *buffer = (char*)PR_Malloc(BUFLEN2);
int g = 0, nopreviewNum;
wallet_MapElement *url;
char* urlCString;
wallet_InitializeURLList();
buffer[0] = '\0';
nopreviewNum = 0;
PRInt32 count = LIST_COUNT(wallet_URL_list);
for (PRInt32 i=0; i<count; i++) {
url = NS_STATIC_CAST(wallet_MapElement*, wallet_URL_list->ElementAt(i));
if (url->item2->CharAt(NO_PREVIEW) == 'y') {
urlCString = url->item1->ToNewCString();
g += PR_snprintf(buffer+g, BUFLEN2-g,
"%c <OPTION value=%d>%s</OPTION>\n",
BREAK,
nopreviewNum,
urlCString
);
delete[] urlCString;
nopreviewNum++;
}
}
aNopreviewList = buffer;
PR_FREEIF(buffer);
}
PUBLIC void
WLLT_GetNocaptureListForViewer(nsString& aNocaptureList)
{
char *buffer = (char*)PR_Malloc(BUFLEN2);
int g = 0, nocaptureNum;
wallet_MapElement *url;
char* urlCString;
wallet_InitializeURLList();
buffer[0] = '\0';
nocaptureNum = 0;
PRInt32 count = LIST_COUNT(wallet_URL_list);
for (PRInt32 i=0; i<count; i++) {
url = NS_STATIC_CAST(wallet_MapElement*, wallet_URL_list->ElementAt(i));
if (url->item2->CharAt(NO_CAPTURE) == 'y') {
urlCString = url->item1->ToNewCString();
g += PR_snprintf(buffer+g, BUFLEN2-g,
"%c <OPTION value=%d>%s</OPTION>\n",
BREAK,
nocaptureNum,
urlCString
);
delete[] urlCString;
nocaptureNum++;
}
}
aNocaptureList = buffer;
PR_FREEIF(buffer);
}
PUBLIC void
WLLT_PostEdit(nsAutoString walletList) {
if (!Wallet_KeySet()) {
return;
}
char* separator;
nsFileSpec dirSpec;
nsresult rv = Wallet_ProfileDirectory(dirSpec);
if (NS_FAILED(rv)) {
return;
}
/* convert walletList to a C string */
char *walletListAsCString = walletList.ToNewCString();
char *nextItem = walletListAsCString;
/* return if OK button was not pressed */
separator = strchr(nextItem, BREAK);
if (!separator) {
delete[] walletListAsCString;
return;
}
*separator = '\0';
if (PL_strcmp(nextItem, "OK")) {
*separator = BREAK;
delete []walletListAsCString;
return;
}
nextItem = separator+1;
*separator = BREAK;
/* open SchemaValue file */
nsOutputFileStream strm(dirSpec + "SchemaValue.tbl");
if (!strm.is_open()) {
NS_ERROR("unable to open file");
delete []walletListAsCString;
return;
}
Wallet_RestartKey();
/* write the values in the walletList to the file */
for (int i=0; (*nextItem != '\0'); i++) {
separator = strchr(nextItem, BREAK);
if (!separator) {
strm.close();
delete[] walletListAsCString;
return;
}
*separator = '\0';
if (NS_FAILED(wallet_PutLine(strm, nextItem, PR_TRUE))) {
break;
}
nextItem = separator+1;
*separator = BREAK;
}
/* close the file and read it back into the SchemaToValue list */
strm.close();
wallet_Clear(&wallet_SchemaToValue_list);
wallet_ReadFromFile("SchemaValue.tbl", wallet_SchemaToValue_list, PR_TRUE, PR_TRUE);
delete []walletListAsCString;
}
PUBLIC void
WLLT_PreEdit(nsAutoString& walletList) {
wallet_Initialize();
if (!Wallet_KeySet()) {
return;
}
walletList = BREAK;
wallet_MapElement * ptr;
PRInt32 count = LIST_COUNT(wallet_SchemaToValue_list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_MapElement*, wallet_SchemaToValue_list->ElementAt(i));
walletList += *(ptr->item1) + BREAK;
if (*ptr->item2 != "") {
walletList += *(ptr->item2) + BREAK;
} else {
wallet_Sublist * ptr1;
PRInt32 count = LIST_COUNT(ptr->itemList);
for (PRInt32 i=0; i<count; i++) {
ptr1 = NS_STATIC_CAST(wallet_Sublist*, ptr->itemList->ElementAt(i));
walletList += *(ptr1->item) + BREAK;
}
}
walletList += BREAK;
}
}
/*
* return after previewing a set of prefills
*/
PUBLIC void
WLLT_PrefillReturn(nsAutoString results) {
char* listAsAscii;
char* fillins;
char* urlName;
char* skip;
nsAutoString * next;
/* get values that are in environment variables */
fillins = SI_FindValueInArgs(results, "|fillins|");
listAsAscii = SI_FindValueInArgs(results, "|list|");
skip = SI_FindValueInArgs(results, "|skip|");
urlName = SI_FindValueInArgs(results, "|url|");
/* add url to url list if user doesn't want to preview this page in the future */
if (!PL_strcmp(skip, "true")) {
nsAutoString * url = new nsAutoString(urlName);
nsVoidArray* dummy;
nsAutoString * value = new nsAutoString("nn");
if (!url || !value) {
wallet_ReadFromList(*url, *value, dummy, wallet_URL_list);
value->SetCharAt('y', NO_PREVIEW);
wallet_WriteToList(*url, *value, dummy, wallet_URL_list, DUP_OVERWRITE);
wallet_WriteToFile("URL.tbl", wallet_URL_list, PR_FALSE);
}
}
/* process the list, doing the fillins */
nsVoidArray * list;
sscanf(listAsAscii, "%ld", &list);
if (fillins[0] == '\0') { /* user pressed CANCEL */
wallet_ReleasePrefillElementList(list);
return;
}
/*
* note: there are two lists involved here and we are stepping through both of them.
* One is the pre-fill list that was generated when we walked through the html content.
* For each pre-fillable item, it contains n entries, one for each possible value that
* can be prefilled for that field. The first entry for each field can be identified
* because it has a non-zero count field (in fact, the count is the number of entries
* for that field), all subsequent entries for the same field have a zero count field.
* The other is the fillin list which was generated by the html dialog that just
* finished. It contains one entry for each pre-fillable item specificying that
* particular value that should be prefilled for that item.
*/
wallet_PrefillElement * ptr;
char * ptr2;
ptr2 = fillins;
/* step through pre-fill list */
PRBool first = PR_TRUE;
PRInt32 count = LIST_COUNT(list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_PrefillElement*, list->ElementAt(i));
/* advance in fillins list each time a new schema name in pre-fill list is encountered */
if (ptr->count != 0) {
/* count != 0 indicates a new schema name */
if (!first) {
delete next;
} else {
first = PR_FALSE;
}
next = wallet_GetNextInString(ptr2);
if (nsnull == next) {
break;
}
if (*next != *ptr->schema) {
break; /* something's wrong so stop prefilling */
}
delete next;
next = wallet_GetNextInString(ptr2);
}
if (*next == *ptr->value) {
/*
* Remove entry from wallet_SchemaToValue_list and then reinsert. This will
* keep multiple values in that list for the same field ordered with
* most-recently-used first. That's useful since the first such entry
* is the default value used for pre-filling.
*/
/*
* Test for ptr->count being zero is an optimization that avoids us from doing a
* reordering if the current entry already was first
*/
if (ptr->count == 0) {
nsAutoString oldValue;
PRInt32 index = 0;
PRInt32 lastIndex = index;
nsVoidArray* dummy;
while(wallet_ReadFromList(*ptr->schema, oldValue, dummy, wallet_SchemaToValue_list, index)) {
if (oldValue == *ptr->value) {
wallet_MapElement * mapElement =
(wallet_MapElement *) (wallet_SchemaToValue_list->ElementAt(lastIndex));
wallet_SchemaToValue_list->RemoveElementAt(lastIndex);
wallet_WriteToList(
*(mapElement->item1),
*(mapElement->item2),
mapElement->itemList,
wallet_SchemaToValue_list);
delete mapElement;
break;
}
lastIndex = index;
}
}
}
/* Change the value */
if ((*next == *ptr->value) || ((ptr->count>0) && (*next == ""))) {
if (((*next == *ptr->value) || (*next == "")) && ptr->inputElement) {
ptr->inputElement->SetValue(*next);
} else {
nsresult result;
result = wallet_GetSelectIndex(ptr->selectElement, *next, ptr->selectIndex);
if (NS_SUCCEEDED(result)) {
ptr->selectElement->SetSelectedIndex(ptr->selectIndex);
} else {
ptr->selectElement->SetSelectedIndex(0);
}
}
}
}
if (next != nsnull ) {
delete next;
}
/* Release the prefill list that was generated when we walked thru the html content */
wallet_ReleasePrefillElementList(list);
}
/*
* get the form elements on the current page and prefill them if possible
*/
PUBLIC nsresult
WLLT_Prefill(nsIPresShell* shell, nsString url, PRBool quick) {
/* create list of elements that can be prefilled */
nsVoidArray *wallet_PrefillElement_list=new nsVoidArray();
if (!wallet_PrefillElement_list) {
return NS_ERROR_FAILURE;
}
/* starting with the present shell, get each form element and put them on a list */
nsresult result;
if (nsnull != shell) {
nsIDocument* doc = nsnull;
result = shell->GetDocument(&doc);
if (NS_SUCCEEDED(result)) {
wallet_Initialize();
wallet_InitializeCurrentURL(doc);
nsIDOMHTMLDocument* htmldoc = nsnull;
nsresult result = doc->QueryInterface(kIDOMHTMLDocumentIID, (void**)&htmldoc);
if ((NS_SUCCEEDED(result)) && (nsnull != htmldoc)) {
nsIDOMHTMLCollection* forms = nsnull;
htmldoc->GetForms(&forms);
if (nsnull != forms) {
PRUint32 numForms;
forms->GetLength(&numForms);
for (PRUint32 formX = 0; formX < numForms; formX++) {
nsIDOMNode* formNode = nsnull;
forms->Item(formX, &formNode);
if (nsnull != formNode) {
nsIDOMHTMLFormElement* formElement = nsnull;
result = formNode->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElement);
if ((NS_SUCCEEDED(result)) && (nsnull != formElement)) {
nsIDOMHTMLCollection* elements = nsnull;
result = formElement->GetElements(&elements);
if ((NS_SUCCEEDED(result)) && (nsnull != elements)) {
/* got to the form elements at long last */
PRUint32 numElements;
elements->GetLength(&numElements);
for (PRUint32 elementX = 0; elementX < numElements; elementX++) {
nsIDOMNode* elementNode = nsnull;
elements->Item(elementX, &elementNode);
if (nsnull != elementNode) {
wallet_PrefillElement * prefillElement;
PRInt32 index = 0;
wallet_PrefillElement * firstElement = nsnull;
PRUint32 numberOfElements = 0;
for (;;) {
/* loop to allow for multiple values */
/* first element in multiple-value group will have its count
* field set to the number of elements in group. All other
* elements in group will have count field set to 0
*/
prefillElement = PR_NEW(wallet_PrefillElement);
if (wallet_GetPrefills
(elementNode,
prefillElement->inputElement,
prefillElement->selectElement,
prefillElement->schema,
prefillElement->value,
prefillElement->selectIndex,
index) != -1) {
/* another value found */
if (nsnull == firstElement) {
firstElement = prefillElement;
}
numberOfElements++;
prefillElement->count = 0;
wallet_PrefillElement_list->AppendElement(prefillElement);
if (index == -1) {
/* value was found from concat rules, can't resume from here */
break;
}
} else {
/* value not found, stop looking for more values */
delete prefillElement;
break;
}
}
if (numberOfElements>0) {
firstElement->count = numberOfElements;
}
NS_RELEASE(elementNode);
}
}
NS_RELEASE(elements);
}
NS_RELEASE(formElement);
}
NS_RELEASE(formNode);
}
}
NS_RELEASE(forms);
}
NS_RELEASE(htmldoc);
}
NS_RELEASE(doc);
}
NS_RELEASE(shell);
}
/* return if no elements were put into the list */
if (LIST_COUNT(wallet_PrefillElement_list) == 0) {
if (Wallet_KeySet()) {
char * message = Wallet_Localize("noPrefills");
Wallet_Alert(message);
PR_FREEIF(message);
}
return NS_ERROR_FAILURE; // indicates to caller not to display preview screen
}
/* prefill each element using the list */
/* determine if url is on list of urls that should not be previewed */
PRBool noPreview = PR_FALSE;
if (!quick) {
wallet_InitializeURLList();
nsVoidArray* dummy;
nsAutoString * value = new nsAutoString("nn");
nsAutoString * urlPtr = new nsAutoString(url);
if (!value || !urlPtr) {
wallet_ReadFromList(*urlPtr, *value, dummy, wallet_URL_list);
noPreview = (value->CharAt(NO_PREVIEW) == 'y');
delete value;
delete urlPtr;
}
}
/* determine if preview is necessary */
if (noPreview || quick) {
/* prefill each element without any preview for user verification */
wallet_PrefillElement * ptr;
PRInt32 count = LIST_COUNT(wallet_PrefillElement_list);
for (PRInt32 i=0; i<count; i++) {
ptr = NS_STATIC_CAST(wallet_PrefillElement*, wallet_PrefillElement_list->ElementAt(i));
if (ptr->count) {
if (ptr->inputElement) {
ptr->inputElement->SetValue(*(ptr->value));
} else {
ptr->selectElement->SetSelectedIndex(ptr->selectIndex);
}
}
}
/* go thru list just generated and release everything */
wallet_ReleasePrefillElementList(wallet_PrefillElement_list);
return NS_ERROR_FAILURE; // indicates to caller not to display preview screen
} else {
/* let user preview and verify the prefills first */
wallet_list = wallet_PrefillElement_list;
wallet_url = url;
#ifdef DEBUG
wallet_DumpStopwatch();
wallet_ClearStopwatch();
//wallet_DumpTiming();
//wallet_ClearTiming();
#endif
return NS_OK; // indicates that caller is to display preview screen
}
}
#define FORM_TYPE_TEXT 1
#define FORM_TYPE_PASSWORD 7
#define MAX_ARRAY_SIZE 500
extern void
SINGSIGN_RememberSignonData
(char* URLName, char** name_array, char** value_array, char** type_array, PRInt32 value_cnt);
PUBLIC void
WLLT_OnSubmit(nsIContent* formNode) {
/* get url name as ascii string */
char *URLName = nsnull;
nsIURI* docURL = nsnull;
nsIDocument* doc = nsnull;
formNode->GetDocument(doc);
#ifdef NECKO
char* spec;
#else
const char* spec;
#endif
if (!doc) {
return;
}
docURL = doc->GetDocumentURL();
if (!docURL) {
return;
}
(void)docURL->GetSpec(&spec);
URLName = (char*)PR_Malloc(PL_strlen(spec)+1);
PL_strcpy(URLName, spec);
NS_IF_RELEASE(docURL);
#ifdef NECKO
nsCRT::free(spec);
#endif
/* get to the form elements */
PRInt32 count = 0;
nsIDOMHTMLFormElement* formElement = nsnull;
nsresult result = formNode->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElement);
if ((NS_SUCCEEDED(result)) && (nsnull != formElement)) {
nsIDOMHTMLCollection* elements = nsnull;
result = formElement->GetElements(&elements);
if ((NS_SUCCEEDED(result)) && (nsnull != elements)) {
char* name_array[MAX_ARRAY_SIZE];
char* value_array[MAX_ARRAY_SIZE];
uint8 type_array[MAX_ARRAY_SIZE];
PRInt32 value_cnt = 0;
/* got to the form elements at long last */
/* now find out how many text fields are on the form */
/* also build arrays for single signon */
PRUint32 numElements;
elements->GetLength(&numElements);
for (PRUint32 elementX = 0; elementX < numElements; elementX++) {
nsIDOMNode* elementNode = nsnull;
elements->Item(elementX, &elementNode);
if (nsnull != elementNode) {
nsIDOMHTMLInputElement* inputElement;
result =
elementNode->QueryInterface(kIDOMHTMLInputElementIID, (void**)&inputElement);
if ((NS_SUCCEEDED(result)) && (nsnull != inputElement)) {
nsAutoString type;
result = inputElement->GetType(type);
if (NS_SUCCEEDED(result)) {
PRBool isText = ((type == "") || (type.Compare("text", PR_TRUE)==0));
PRBool isPassword = (type.Compare("password", PR_TRUE)==0);
if (isText) {
count++;
}
if (value_cnt < MAX_ARRAY_SIZE) {
if (isText) {
type_array[value_cnt] = FORM_TYPE_TEXT;
} else if (isPassword) {
type_array[value_cnt] = FORM_TYPE_PASSWORD;
}
nsAutoString value;
result = inputElement->GetValue(value);
if (NS_SUCCEEDED(result)) {
nsAutoString field;
result = inputElement->GetName(field);
if (NS_SUCCEEDED(result)) {
value_array[value_cnt] = value.ToNewCString();
name_array[value_cnt] = field.ToNewCString();
value_cnt++;
}
}
}
}
NS_RELEASE(inputElement);
}
NS_RELEASE(elementNode);
}
}
/* save login if appropriate */
SINGSIGN_RememberSignonData
(URLName, (char**)name_array, (char**)value_array, (char**)type_array, value_cnt);
/* save form if it meets all necessary conditions */
if (wallet_GetFormsCapturingPref() && (count>=3) && wallet_OKToCapture(URLName)) {
/* conditions all met, now save it */
for (PRUint32 elementX = 0; elementX < numElements; elementX++) {
nsIDOMNode* elementNode = nsnull;
elements->Item(elementX, &elementNode);
if (nsnull != elementNode) {
nsIDOMHTMLInputElement* inputElement;
result =
elementNode->QueryInterface(kIDOMHTMLInputElementIID, (void**)&inputElement);
if ((NS_SUCCEEDED(result)) && (nsnull != inputElement)) {
/* it's an input element */
nsAutoString type;
result = inputElement->GetType(type);
if ((NS_SUCCEEDED(result)) &&
((type =="") || (type.Compare("text", PR_TRUE) == 0))) {
nsAutoString field;
result = inputElement->GetName(field);
if (NS_SUCCEEDED(result)) {
nsAutoString value;
result = inputElement->GetValue(value);
if (NS_SUCCEEDED(result)) {
/* get schema name from vcard attribute if it exists */
nsAutoString vcardValue("");
nsIDOMElement * element;
result = elementNode->QueryInterface(kIDOMElementIID, (void**)&element);
if ((NS_SUCCEEDED(result)) && (nsnull != element)) {
nsAutoString vcardName("VCARD_NAME");
result = element->GetAttribute(vcardName, vcardValue);
NS_RELEASE(element);
}
wallet_Capture(doc, field, value, vcardValue);
}
}
}
NS_RELEASE(inputElement);
}
NS_RELEASE(elementNode);
}
}
}
NS_RELEASE(elements);
}
NS_RELEASE(formElement);
}
}
PUBLIC void
WLLT_FetchFromNetCenter() {
/* temporary patch to avoid bug 11766 */
return;
nsresult rv;
nsFileSpec dirSpec;
rv = Wallet_ResourceDirectory(dirSpec);
if (NS_FAILED(rv)) {
return;
}
rv = NS_NewURItoFile("http://people.netscape.com/morse/wallet/URLFieldSchema.tbl",
dirSpec, "URLFieldSchema.tbl");
if (NS_FAILED(rv)) {
return;
}
rv = NS_NewURItoFile("http://people.netscape.com/morse/wallet/SchemaConcat.tbl",
dirSpec, "SchemaConcat.tbl");
if (NS_FAILED(rv)) {
return;
}
rv = NS_NewURItoFile("http://people.netscape.com/morse/wallet/FieldSchema.tbl",
dirSpec, "FieldSchema.tbl");
if (NS_FAILED(rv)) {
return;
}
}