summaryrefslogtreecommitdiff
path: root/mozilla/security/nss/lib/base
diff options
context:
space:
mode:
authorLorry <lorry@roadtrain.codethink.co.uk>2012-07-18 20:31:20 +0100
committerLorry <lorry@roadtrain.codethink.co.uk>2012-07-18 20:31:20 +0100
commite43ad1f4ce7f1504e6f01fc8a90d5c0398013383 (patch)
tree03504d9d81336081b899c9f34cc0f66801caf67c /mozilla/security/nss/lib/base
downloadnss-e43ad1f4ce7f1504e6f01fc8a90d5c0398013383.tar.gz
Tarball conversion
Diffstat (limited to 'mozilla/security/nss/lib/base')
-rw-r--r--mozilla/security/nss/lib/base/Makefile44
-rw-r--r--mozilla/security/nss/lib/base/arena.c1158
-rw-r--r--mozilla/security/nss/lib/base/base.h1430
-rw-r--r--mozilla/security/nss/lib/base/baset.h161
-rw-r--r--mozilla/security/nss/lib/base/config.mk52
-rw-r--r--mozilla/security/nss/lib/base/error.c305
-rw-r--r--mozilla/security/nss/lib/base/errorval.c98
-rw-r--r--mozilla/security/nss/lib/base/hash.c409
-rw-r--r--mozilla/security/nss/lib/base/hashops.c120
-rw-r--r--mozilla/security/nss/lib/base/item.c244
-rw-r--r--mozilla/security/nss/lib/base/libc.c200
-rw-r--r--mozilla/security/nss/lib/base/list.c437
-rw-r--r--mozilla/security/nss/lib/base/manifest.mn71
-rw-r--r--mozilla/security/nss/lib/base/nssbase.h170
-rw-r--r--mozilla/security/nss/lib/base/nssbaset.h155
-rw-r--r--mozilla/security/nss/lib/base/tracker.c447
-rw-r--r--mozilla/security/nss/lib/base/utf8.c762
17 files changed, 6263 insertions, 0 deletions
diff --git a/mozilla/security/nss/lib/base/Makefile b/mozilla/security/nss/lib/base/Makefile
new file mode 100644
index 0000000..a2b1449
--- /dev/null
+++ b/mozilla/security/nss/lib/base/Makefile
@@ -0,0 +1,44 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# 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 the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+MAKEFILE_CVS_ID = "@(#) $RCSfile: Makefile,v $ $Revision: 1.4 $ $Date: 2005/01/20 02:25:45 $"
+
+include manifest.mn
+include $(CORE_DEPTH)/coreconf/config.mk
+include config.mk
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+export:: private_export
diff --git a/mozilla/security/nss/lib/base/arena.c b/mozilla/security/nss/lib/base/arena.c
new file mode 100644
index 0000000..eeca9b2
--- /dev/null
+++ b/mozilla/security/nss/lib/base/arena.c
@@ -0,0 +1,1158 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: arena.c,v $ $Revision: 1.13 $ $Date: 2010/03/15 08:29:31 $";
+#endif /* DEBUG */
+
+/*
+ * arena.c
+ *
+ * This contains the implementation of NSS's thread-safe arenas.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+#ifdef ARENA_THREADMARK
+#include "prthread.h"
+#endif /* ARENA_THREADMARK */
+
+#include "prlock.h"
+#include "plarena.h"
+
+#include <string.h>
+
+/*
+ * NSSArena
+ *
+ * This is based on NSPR's arena code, but it is threadsafe.
+ *
+ * The public methods relating to this type are:
+ *
+ * NSSArena_Create -- constructor
+ * NSSArena_Destroy
+ *
+ * The nonpublic methods relating to this type are:
+ *
+ * nssArena_Create -- constructor
+ * nssArena_Destroy
+ * nssArena_Mark
+ * nssArena_Release
+ * nssArena_Unmark
+ *
+ * nss_ZAlloc
+ * nss_ZFreeIf
+ * nss_ZRealloc
+ *
+ * In debug builds, the following calls are available:
+ *
+ * nssArena_verifyPointer
+ * nssArena_registerDestructor
+ * nssArena_deregisterDestructor
+ */
+
+struct NSSArenaStr {
+ PLArenaPool pool;
+ PRLock *lock;
+#ifdef ARENA_THREADMARK
+ PRThread *marking_thread;
+ nssArenaMark *first_mark;
+ nssArenaMark *last_mark;
+#endif /* ARENA_THREADMARK */
+#ifdef ARENA_DESTRUCTOR_LIST
+ struct arena_destructor_node *first_destructor;
+ struct arena_destructor_node *last_destructor;
+#endif /* ARENA_DESTRUCTOR_LIST */
+};
+
+/*
+ * nssArenaMark
+ *
+ * This type is used to mark the current state of an NSSArena.
+ */
+
+struct nssArenaMarkStr {
+ PRUint32 magic;
+ void *mark;
+#ifdef ARENA_THREADMARK
+ nssArenaMark *next;
+#endif /* ARENA_THREADMARK */
+#ifdef ARENA_DESTRUCTOR_LIST
+ struct arena_destructor_node *next_destructor;
+ struct arena_destructor_node *prev_destructor;
+#endif /* ARENA_DESTRUCTOR_LIST */
+};
+
+#define MARK_MAGIC 0x4d41524b /* "MARK" how original */
+
+/*
+ * But first, the pointer-tracking code
+ */
+#ifdef DEBUG
+extern const NSSError NSS_ERROR_INTERNAL_ERROR;
+
+static nssPointerTracker arena_pointer_tracker;
+
+static PRStatus
+arena_add_pointer
+(
+ const NSSArena *arena
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_initialize(&arena_pointer_tracker);
+ if( PR_SUCCESS != rv ) {
+ return rv;
+ }
+
+ rv = nssPointerTracker_add(&arena_pointer_tracker, arena);
+ if( PR_SUCCESS != rv ) {
+ NSSError e = NSS_GetError();
+ if( NSS_ERROR_NO_MEMORY != e ) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ }
+
+ return rv;
+ }
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+arena_remove_pointer
+(
+ const NSSArena *arena
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_remove(&arena_pointer_tracker, arena);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ }
+
+ return rv;
+}
+
+/*
+ * nssArena_verifyPointer
+ *
+ * This method is only present in debug builds.
+ *
+ * If the specified pointer is a valid pointer to an NSSArena object,
+ * this routine will return PR_SUCCESS. Otherwise, it will put an
+ * error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ *
+ * Return value:
+ * PR_SUCCESS if the pointer is valid
+ * PR_FAILURE if it isn't
+ */
+
+NSS_IMPLEMENT PRStatus
+nssArena_verifyPointer
+(
+ const NSSArena *arena
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_initialize(&arena_pointer_tracker);
+ if( PR_SUCCESS != rv ) {
+ /*
+ * This is a little disingenious. We have to initialize the
+ * tracker, because someone could "legitimately" try to verify
+ * an arena pointer before one is ever created. And this step
+ * might fail, due to lack of memory. But the only way that
+ * this step can fail is if it's doing the call_once stuff,
+ * (later calls just no-op). And if it didn't no-op, there
+ * aren't any valid arenas.. so the argument certainly isn't one.
+ */
+ nss_SetError(NSS_ERROR_INVALID_ARENA);
+ return PR_FAILURE;
+ }
+
+ rv = nssPointerTracker_verify(&arena_pointer_tracker, arena);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_INVALID_ARENA);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif /* DEBUG */
+
+#ifdef ARENA_DESTRUCTOR_LIST
+
+struct arena_destructor_node {
+ struct arena_destructor_node *next;
+ struct arena_destructor_node *prev;
+ void (*destructor)(void *argument);
+ void *arg;
+};
+
+/*
+ * nssArena_registerDestructor
+ *
+ * This routine stores a pointer to a callback and an arbitrary
+ * pointer-sized argument in the arena, at the current point in
+ * the mark stack. If the arena is destroyed, or an "earlier"
+ * mark is released, then this destructor will be called at that
+ * time. Note that the destructor will be called with the arena
+ * locked, which means the destructor may free memory in that
+ * arena, but it may not allocate or cause to be allocated any
+ * memory. This callback facility was included to support our
+ * debug-version pointer-tracker feature; overuse runs counter to
+ * the the original intent of arenas. This routine returns a
+ * PRStatus value; if successful, it will return PR_SUCCESS. If
+ * unsuccessful, it will set an error on the error stack and
+ * return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssArena_registerDestructor
+(
+ NSSArena *arena,
+ void (*destructor)(void *argument),
+ void *arg
+)
+{
+ struct arena_destructor_node *it;
+
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return PR_FAILURE;
+ }
+#endif /* NSSDEBUG */
+
+ it = nss_ZNEW(arena, struct arena_destructor_node);
+ if( (struct arena_destructor_node *)NULL == it ) {
+ return PR_FAILURE;
+ }
+
+ it->prev = arena->last_destructor;
+ arena->last_destructor->next = it;
+ arena->last_destructor = it;
+ it->destructor = destructor;
+ it->arg = arg;
+
+ if( (nssArenaMark *)NULL != arena->last_mark ) {
+ arena->last_mark->prev_destructor = it->prev;
+ arena->last_mark->next_destructor = it->next;
+ }
+
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRStatus
+nssArena_deregisterDestructor
+(
+ NSSArena *arena,
+ void (*destructor)(void *argument),
+ void *arg
+)
+{
+ struct arena_destructor_node *it;
+
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return PR_FAILURE;
+ }
+#endif /* NSSDEBUG */
+
+ for( it = arena->first_destructor; it; it = it->next ) {
+ if( (it->destructor == destructor) && (it->arg == arg) ) {
+ break;
+ }
+ }
+
+ if( (struct arena_destructor_node *)NULL == it ) {
+ nss_SetError(NSS_ERROR_NOT_FOUND);
+ return PR_FAILURE;
+ }
+
+ if( it == arena->first_destructor ) {
+ arena->first_destructor = it->next;
+ }
+
+ if( it == arena->last_destructor ) {
+ arena->last_destructor = it->prev;
+ }
+
+ if( (struct arena_destructor_node *)NULL != it->prev ) {
+ it->prev->next = it->next;
+ }
+
+ if( (struct arena_destructor_node *)NULL != it->next ) {
+ it->next->prev = it->prev;
+ }
+
+ {
+ nssArenaMark *m;
+ for( m = arena->first_mark; m; m = m->next ) {
+ if( m->next_destructor == it ) {
+ m->next_destructor = it->next;
+ }
+ if( m->prev_destructor == it ) {
+ m->prev_destructor = it->prev;
+ }
+ }
+ }
+
+ nss_ZFreeIf(it);
+ return PR_SUCCESS;
+}
+
+static void
+nss_arena_call_destructor_chain
+(
+ struct arena_destructor_node *it
+)
+{
+ for( ; it ; it = it->next ) {
+ (*(it->destructor))(it->arg);
+ }
+}
+
+#endif /* ARENA_DESTRUCTOR_LIST */
+
+/*
+ * NSSArena_Create
+ *
+ * This routine creates a new memory arena. This routine may return
+ * NULL upon error, in which case it will have created an error stack.
+ *
+ * The top-level error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an NSSArena upon success
+ */
+
+NSS_IMPLEMENT NSSArena *
+NSSArena_Create
+(
+ void
+)
+{
+ nss_ClearErrorStack();
+ return nssArena_Create();
+}
+
+/*
+ * nssArena_Create
+ *
+ * This routine creates a new memory arena. This routine may return
+ * NULL upon error, in which case it will have set an error on the
+ * error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an NSSArena upon success
+ */
+
+NSS_IMPLEMENT NSSArena *
+nssArena_Create
+(
+ void
+)
+{
+ NSSArena *rv = (NSSArena *)NULL;
+
+ rv = nss_ZNEW((NSSArena *)NULL, NSSArena);
+ if( (NSSArena *)NULL == rv ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (NSSArena *)NULL;
+ }
+
+ rv->lock = PR_NewLock();
+ if( (PRLock *)NULL == rv->lock ) {
+ (void)nss_ZFreeIf(rv);
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (NSSArena *)NULL;
+ }
+
+ /*
+ * Arena sizes. The current security code has 229 occurrences of
+ * PORT_NewArena. The default chunksizes specified break down as
+ *
+ * Size Mult. Specified as
+ * 512 1 512
+ * 1024 7 1024
+ * 2048 5 2048
+ * 2048 5 CRMF_DEFAULT_ARENA_SIZE
+ * 2048 190 DER_DEFAULT_CHUNKSIZE
+ * 2048 20 SEC_ASN1_DEFAULT_ARENA_SIZE
+ * 4096 1 4096
+ *
+ * Obviously this "default chunksize" flexibility isn't very
+ * useful to us, so I'll just pick 2048.
+ */
+
+ PL_InitArenaPool(&rv->pool, "NSS", 2048, sizeof(double));
+
+#ifdef DEBUG
+ {
+ PRStatus st;
+ st = arena_add_pointer(rv);
+ if( PR_SUCCESS != st ) {
+ PL_FinishArenaPool(&rv->pool);
+ PR_DestroyLock(rv->lock);
+ (void)nss_ZFreeIf(rv);
+ return (NSSArena *)NULL;
+ }
+ }
+#endif /* DEBUG */
+
+ return rv;
+}
+
+/*
+ * NSSArena_Destroy
+ *
+ * This routine will destroy the specified arena, freeing all memory
+ * allocated from it. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCESS. If unsuccessful, it will
+ * create an error stack and return PR_FAILURE.
+ *
+ * The top-level error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ *
+ * Return value:
+ * PR_SUCCESS upon success
+ * PR_FAILURE upon failure
+ */
+
+NSS_IMPLEMENT PRStatus
+NSSArena_Destroy
+(
+ NSSArena *arena
+)
+{
+ nss_ClearErrorStack();
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ return nssArena_Destroy(arena);
+}
+
+/*
+ * nssArena_Destroy
+ *
+ * This routine will destroy the specified arena, freeing all memory
+ * allocated from it. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCESS. If unsuccessful, it will
+ * set an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssArena_Destroy
+(
+ NSSArena *arena
+)
+{
+ PRLock *lock;
+
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return PR_FAILURE;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRLock *)NULL == arena->lock ) {
+ /* Just got destroyed */
+ nss_SetError(NSS_ERROR_INVALID_ARENA);
+ return PR_FAILURE;
+ }
+ PR_Lock(arena->lock);
+
+#ifdef DEBUG
+ if( PR_SUCCESS != arena_remove_pointer(arena) ) {
+ PR_Unlock(arena->lock);
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+#ifdef ARENA_DESTRUCTOR_LIST
+ /* Note that the arena is locked at this time */
+ nss_arena_call_destructor_chain(arena->first_destructor);
+#endif /* ARENA_DESTRUCTOR_LIST */
+
+ PL_FinishArenaPool(&arena->pool);
+ lock = arena->lock;
+ arena->lock = (PRLock *)NULL;
+ PR_Unlock(lock);
+ PR_DestroyLock(lock);
+ (void)nss_ZFreeIf(arena);
+ return PR_SUCCESS;
+}
+
+static void *nss_zalloc_arena_locked(NSSArena *arena, PRUint32 size);
+
+/*
+ * nssArena_Mark
+ *
+ * This routine "marks" the current state of an arena. Space
+ * allocated after the arena has been marked can be freed by
+ * releasing the arena back to the mark with nssArena_Release,
+ * or committed by calling nssArena_Unmark. When successful,
+ * this routine returns a valid nssArenaMark pointer. This
+ * routine may return NULL upon error, in which case it will
+ * have set an error on the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon failure
+ * An nssArenaMark pointer upon success
+ */
+
+NSS_IMPLEMENT nssArenaMark *
+nssArena_Mark
+(
+ NSSArena *arena
+)
+{
+ nssArenaMark *rv;
+ void *p;
+
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return (nssArenaMark *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRLock *)NULL == arena->lock ) {
+ /* Just got destroyed */
+ nss_SetError(NSS_ERROR_INVALID_ARENA);
+ return (nssArenaMark *)NULL;
+ }
+ PR_Lock(arena->lock);
+
+#ifdef ARENA_THREADMARK
+ if( (PRThread *)NULL == arena->marking_thread ) {
+ /* Unmarked. Store our thread ID */
+ arena->marking_thread = PR_GetCurrentThread();
+ /* This call never fails. */
+ } else {
+ /* Marked. Verify it's the current thread */
+ if( PR_GetCurrentThread() != arena->marking_thread ) {
+ PR_Unlock(arena->lock);
+ nss_SetError(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD);
+ return (nssArenaMark *)NULL;
+ }
+ }
+#endif /* ARENA_THREADMARK */
+
+ p = PL_ARENA_MARK(&arena->pool);
+ /* No error possible */
+
+ /* Do this after the mark */
+ rv = (nssArenaMark *)nss_zalloc_arena_locked(arena, sizeof(nssArenaMark));
+ if( (nssArenaMark *)NULL == rv ) {
+ PR_Unlock(arena->lock);
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (nssArenaMark *)NULL;
+ }
+
+#ifdef ARENA_THREADMARK
+ if ( (nssArenaMark *)NULL == arena->first_mark) {
+ arena->first_mark = rv;
+ arena->last_mark = rv;
+ } else {
+ arena->last_mark->next = rv;
+ arena->last_mark = rv;
+ }
+#endif /* ARENA_THREADMARK */
+
+ rv->mark = p;
+ rv->magic = MARK_MAGIC;
+
+#ifdef ARENA_DESTRUCTOR_LIST
+ rv->prev_destructor = arena->last_destructor;
+#endif /* ARENA_DESTRUCTOR_LIST */
+
+ PR_Unlock(arena->lock);
+
+ return rv;
+}
+
+/*
+ * nss_arena_unmark_release
+ *
+ * This static routine implements the routines nssArena_Release
+ * ans nssArena_Unmark, which are almost identical.
+ */
+
+static PRStatus
+nss_arena_unmark_release
+(
+ NSSArena *arena,
+ nssArenaMark *arenaMark,
+ PRBool release
+)
+{
+ void *inner_mark;
+
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return PR_FAILURE;
+ }
+#endif /* NSSDEBUG */
+
+ if( MARK_MAGIC != arenaMark->magic ) {
+ nss_SetError(NSS_ERROR_INVALID_ARENA_MARK);
+ return PR_FAILURE;
+ }
+
+ if( (PRLock *)NULL == arena->lock ) {
+ /* Just got destroyed */
+ nss_SetError(NSS_ERROR_INVALID_ARENA);
+ return PR_FAILURE;
+ }
+ PR_Lock(arena->lock);
+
+#ifdef ARENA_THREADMARK
+ if( (PRThread *)NULL != arena->marking_thread ) {
+ if( PR_GetCurrentThread() != arena->marking_thread ) {
+ PR_Unlock(arena->lock);
+ nss_SetError(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD);
+ return PR_FAILURE;
+ }
+ }
+#endif /* ARENA_THREADMARK */
+
+ if( MARK_MAGIC != arenaMark->magic ) {
+ /* Just got released */
+ PR_Unlock(arena->lock);
+ nss_SetError(NSS_ERROR_INVALID_ARENA_MARK);
+ return PR_FAILURE;
+ }
+
+ arenaMark->magic = 0;
+ inner_mark = arenaMark->mark;
+
+#ifdef ARENA_THREADMARK
+ {
+ nssArenaMark **pMark = &arena->first_mark;
+ nssArenaMark *rest;
+ nssArenaMark *last = (nssArenaMark *)NULL;
+
+ /* Find this mark */
+ while( *pMark != arenaMark ) {
+ last = *pMark;
+ pMark = &(*pMark)->next;
+ }
+
+ /* Remember the pointer, then zero it */
+ rest = (*pMark)->next;
+ *pMark = (nssArenaMark *)NULL;
+
+ arena->last_mark = last;
+
+ /* Invalidate any later marks being implicitly released */
+ for( ; (nssArenaMark *)NULL != rest; rest = rest->next ) {
+ rest->magic = 0;
+ }
+
+ /* If we just got rid of the first mark, clear the thread ID */
+ if( (nssArenaMark *)NULL == arena->first_mark ) {
+ arena->marking_thread = (PRThread *)NULL;
+ }
+ }
+#endif /* ARENA_THREADMARK */
+
+ if( release ) {
+#ifdef ARENA_DESTRUCTOR_LIST
+ if( (struct arena_destructor_node *)NULL != arenaMark->prev_destructor ) {
+ arenaMark->prev_destructor->next = (struct arena_destructor_node *)NULL;
+ }
+ arena->last_destructor = arenaMark->prev_destructor;
+
+ /* Note that the arena is locked at this time */
+ nss_arena_call_destructor_chain(arenaMark->next_destructor);
+#endif /* ARENA_DESTRUCTOR_LIST */
+
+ PR_ARENA_RELEASE(&arena->pool, inner_mark);
+ /* No error return */
+ }
+
+ PR_Unlock(arena->lock);
+ return PR_SUCCESS;
+}
+
+/*
+ * nssArena_Release
+ *
+ * This routine invalidates and releases all memory allocated from
+ * the specified arena after the point at which the specified mark
+ * was obtained. This routine returns a PRStatus value; if successful,
+ * it will return PR_SUCCESS. If unsuccessful, it will set an error
+ * on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_ARENA_MARK
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssArena_Release
+(
+ NSSArena *arena,
+ nssArenaMark *arenaMark
+)
+{
+ return nss_arena_unmark_release(arena, arenaMark, PR_TRUE);
+}
+
+/*
+ * nssArena_Unmark
+ *
+ * This routine "commits" the indicated mark and any marks after
+ * it, making them unreleasable. Note that any earlier marks can
+ * still be released, and such a release will invalidate these
+ * later unmarked regions. If an arena is to be safely shared by
+ * more than one thread, all marks must be either released or
+ * unmarked. This routine returns a PRStatus value; if successful,
+ * it will return PR_SUCCESS. If unsuccessful, it will set an error
+ * on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_ARENA_MARK
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssArena_Unmark
+(
+ NSSArena *arena,
+ nssArenaMark *arenaMark
+)
+{
+ return nss_arena_unmark_release(arena, arenaMark, PR_FALSE);
+}
+
+/*
+ * We prefix this header to all allocated blocks. It is a multiple
+ * of the alignment size. Note that this usage of a header may make
+ * purify spew bogus warnings about "potentially leaked blocks" of
+ * memory; if that gets too annoying we can add in a pointer to the
+ * header in the header itself. There's not a lot of safety here;
+ * maybe we should add a magic value?
+ */
+struct pointer_header {
+ NSSArena *arena;
+ PRUint32 size;
+};
+
+static void *
+nss_zalloc_arena_locked
+(
+ NSSArena *arena,
+ PRUint32 size
+)
+{
+ void *p;
+ void *rv;
+ struct pointer_header *h;
+ PRUint32 my_size = size + sizeof(struct pointer_header);
+ PR_ARENA_ALLOCATE(p, &arena->pool, my_size);
+ if( (void *)NULL == p ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (void *)NULL;
+ }
+ /*
+ * Do this before we unlock. This way if the user is using
+ * an arena in one thread while destroying it in another, he'll
+ * fault/FMR in his code, not ours.
+ */
+ h = (struct pointer_header *)p;
+ h->arena = arena;
+ h->size = size;
+ rv = (void *)((char *)h + sizeof(struct pointer_header));
+ (void)nsslibc_memset(rv, 0, size);
+ return rv;
+}
+
+/*
+ * nss_ZAlloc
+ *
+ * This routine allocates and zeroes a section of memory of the
+ * size, and returns to the caller a pointer to that memory. If
+ * the optional arena argument is non-null, the memory will be
+ * obtained from that arena; otherwise, the memory will be obtained
+ * from the heap. This routine may return NULL upon error, in
+ * which case it will have set an error upon the error stack. The
+ * value specified for size may be zero; in which case a valid
+ * zero-length block of memory will be allocated. This block may
+ * be expanded by calling nss_ZRealloc.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the new segment of zeroed memory
+ */
+
+NSS_IMPLEMENT void *
+nss_ZAlloc
+(
+ NSSArena *arenaOpt,
+ PRUint32 size
+)
+{
+ struct pointer_header *h;
+ PRUint32 my_size = size + sizeof(struct pointer_header);
+
+ if( my_size < sizeof(struct pointer_header) ) {
+ /* Wrapped */
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (void *)NULL;
+ }
+
+ if( (NSSArena *)NULL == arenaOpt ) {
+ /* Heap allocation, no locking required. */
+ h = (struct pointer_header *)PR_Calloc(1, my_size);
+ if( (struct pointer_header *)NULL == h ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (void *)NULL;
+ }
+
+ h->arena = (NSSArena *)NULL;
+ h->size = size;
+ /* We used calloc: it's already zeroed */
+
+ return (void *)((char *)h + sizeof(struct pointer_header));
+ } else {
+ void *rv;
+ /* Arena allocation */
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (void *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRLock *)NULL == arenaOpt->lock ) {
+ /* Just got destroyed */
+ nss_SetError(NSS_ERROR_INVALID_ARENA);
+ return (void *)NULL;
+ }
+ PR_Lock(arenaOpt->lock);
+
+#ifdef ARENA_THREADMARK
+ if( (PRThread *)NULL != arenaOpt->marking_thread ) {
+ if( PR_GetCurrentThread() != arenaOpt->marking_thread ) {
+ nss_SetError(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD);
+ PR_Unlock(arenaOpt->lock);
+ return (void *)NULL;
+ }
+ }
+#endif /* ARENA_THREADMARK */
+
+ rv = nss_zalloc_arena_locked(arenaOpt, size);
+
+ PR_Unlock(arenaOpt->lock);
+ return rv;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * nss_ZFreeIf
+ *
+ * If the specified pointer is non-null, then the region of memory
+ * to which it points -- which must have been allocated with
+ * nss_ZAlloc -- will be zeroed and released. This routine
+ * returns a PRStatus value; if successful, it will return PR_SUCCESS.
+ * If unsuccessful, it will set an error on the error stack and return
+ * PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nss_ZFreeIf
+(
+ void *pointer
+)
+{
+ struct pointer_header *h;
+
+ if( (void *)NULL == pointer ) {
+ return PR_SUCCESS;
+ }
+
+ h = (struct pointer_header *)((char *)pointer
+ - sizeof(struct pointer_header));
+
+ /* Check any magic here */
+
+ if( (NSSArena *)NULL == h->arena ) {
+ /* Heap */
+ (void)nsslibc_memset(pointer, 0, h->size);
+ PR_Free(h);
+ return PR_SUCCESS;
+ } else {
+ /* Arena */
+#ifdef NSSDEBUG
+ if( PR_SUCCESS != nssArena_verifyPointer(h->arena) ) {
+ return PR_FAILURE;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRLock *)NULL == h->arena->lock ) {
+ /* Just got destroyed.. so this pointer is invalid */
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FAILURE;
+ }
+ PR_Lock(h->arena->lock);
+
+ (void)nsslibc_memset(pointer, 0, h->size);
+
+ /* No way to "free" it within an NSPR arena. */
+
+ PR_Unlock(h->arena->lock);
+ return PR_SUCCESS;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * nss_ZRealloc
+ *
+ * This routine reallocates a block of memory obtained by calling
+ * nss_ZAlloc or nss_ZRealloc. The portion of memory
+ * between the new and old sizes -- which is either being newly
+ * obtained or released -- is in either case zeroed. This routine
+ * may return NULL upon failure, in which case it will have placed
+ * an error on the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the replacement segment of memory
+ */
+
+NSS_EXTERN void *
+nss_ZRealloc
+(
+ void *pointer,
+ PRUint32 newSize
+)
+{
+ NSSArena *arena;
+ struct pointer_header *h, *new_h;
+ PRUint32 my_newSize = newSize + sizeof(struct pointer_header);
+ void *rv;
+
+ if( my_newSize < sizeof(struct pointer_header) ) {
+ /* Wrapped */
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (void *)NULL;
+ }
+
+ if( (void *)NULL == pointer ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (void *)NULL;
+ }
+
+ h = (struct pointer_header *)((char *)pointer
+ - sizeof(struct pointer_header));
+
+ /* Check any magic here */
+
+ if( newSize == h->size ) {
+ /* saves thrashing */
+ return pointer;
+ }
+
+ arena = h->arena;
+ if (!arena) {
+ /* Heap */
+ new_h = (struct pointer_header *)PR_Calloc(1, my_newSize);
+ if( (struct pointer_header *)NULL == new_h ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (void *)NULL;
+ }
+
+ new_h->arena = (NSSArena *)NULL;
+ new_h->size = newSize;
+ rv = (void *)((char *)new_h + sizeof(struct pointer_header));
+
+ if( newSize > h->size ) {
+ (void)nsslibc_memcpy(rv, pointer, h->size);
+ (void)nsslibc_memset(&((char *)rv)[ h->size ],
+ 0, (newSize - h->size));
+ } else {
+ (void)nsslibc_memcpy(rv, pointer, newSize);
+ }
+
+ (void)nsslibc_memset(pointer, 0, h->size);
+ h->size = 0;
+ PR_Free(h);
+
+ return rv;
+ } else {
+ void *p;
+ /* Arena */
+#ifdef NSSDEBUG
+ if (PR_SUCCESS != nssArena_verifyPointer(arena)) {
+ return (void *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ if (!arena->lock) {
+ /* Just got destroyed.. so this pointer is invalid */
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (void *)NULL;
+ }
+ PR_Lock(arena->lock);
+
+#ifdef ARENA_THREADMARK
+ if (arena->marking_thread) {
+ if (PR_GetCurrentThread() != arena->marking_thread) {
+ PR_Unlock(arena->lock);
+ nss_SetError(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD);
+ return (void *)NULL;
+ }
+ }
+#endif /* ARENA_THREADMARK */
+
+ if( newSize < h->size ) {
+ /*
+ * We have no general way of returning memory to the arena
+ * (mark/release doesn't work because things may have been
+ * allocated after this object), so the memory is gone
+ * anyway. We might as well just return the same pointer to
+ * the user, saying "yeah, uh-hunh, you can only use less of
+ * it now." We'll zero the leftover part, of course. And
+ * in fact we might as well *not* adjust h->size-- this way,
+ * if the user reallocs back up to something not greater than
+ * the original size, then voila, there's the memory! This
+ * way a thrash big/small/big/small doesn't burn up the arena.
+ */
+ char *extra = &((char *)pointer)[ newSize ];
+ (void)nsslibc_memset(extra, 0, (h->size - newSize));
+ PR_Unlock(arena->lock);
+ return pointer;
+ }
+
+ PR_ARENA_ALLOCATE(p, &arena->pool, my_newSize);
+ if( (void *)NULL == p ) {
+ PR_Unlock(arena->lock);
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (void *)NULL;
+ }
+
+ new_h = (struct pointer_header *)p;
+ new_h->arena = arena;
+ new_h->size = newSize;
+ rv = (void *)((char *)new_h + sizeof(struct pointer_header));
+ if (rv != pointer) {
+ (void)nsslibc_memcpy(rv, pointer, h->size);
+ (void)nsslibc_memset(pointer, 0, h->size);
+ }
+ (void)nsslibc_memset(&((char *)rv)[ h->size ], 0, (newSize - h->size));
+ h->arena = (NSSArena *)NULL;
+ h->size = 0;
+ PR_Unlock(arena->lock);
+ return rv;
+ }
+ /*NOTREACHED*/
+}
+
+PRStatus
+nssArena_Shutdown(void)
+{
+ PRStatus rv = PR_SUCCESS;
+#ifdef DEBUG
+ rv = nssPointerTracker_finalize(&arena_pointer_tracker);
+#endif
+ return rv;
+}
diff --git a/mozilla/security/nss/lib/base/base.h b/mozilla/security/nss/lib/base/base.h
new file mode 100644
index 0000000..01be186
--- /dev/null
+++ b/mozilla/security/nss/lib/base/base.h
@@ -0,0 +1,1430 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef BASE_H
+#define BASE_H
+
+#ifdef DEBUG
+static const char BASE_CVS_ID[] = "@(#) $RCSfile: base.h,v $ $Revision: 1.20 $ $Date: 2008/05/10 01:03:14 $";
+#endif /* DEBUG */
+
+/*
+ * base.h
+ *
+ * This header file contains basic prototypes and preprocessor
+ * definitions used throughout nss but not available publicly.
+ */
+
+#ifndef BASET_H
+#include "baset.h"
+#endif /* BASET_H */
+
+#ifndef NSSBASE_H
+#include "nssbase.h"
+#endif /* NSSBASE_H */
+
+#include "plhash.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * NSSArena
+ *
+ * The nonpublic methods relating to this type are:
+ *
+ * nssArena_Create -- constructor
+ * nssArena_Destroy
+ * nssArena_Mark
+ * nssArena_Release
+ * nssArena_Unmark
+ *
+ * nss_ZAlloc
+ * nss_ZFreeIf
+ * nss_ZRealloc
+ *
+ * Additionally, there are some preprocessor macros:
+ *
+ * nss_ZNEW
+ * nss_ZNEWARRAY
+ *
+ * In debug builds, the following calls are available:
+ *
+ * nssArena_verifyPointer
+ * nssArena_registerDestructor
+ * nssArena_deregisterDestructor
+ *
+ * The following preprocessor macro is also always available:
+ *
+ * nssArena_VERIFYPOINTER
+ *
+ * A constant PLHashAllocOps structure is available for users
+ * of the NSPL PLHashTable routines.
+ *
+ * nssArenaHashAllocOps
+ */
+
+/*
+ * nssArena_Create
+ *
+ * This routine creates a new memory arena. This routine may return
+ * NULL upon error, in which case it will have set an error on the
+ * error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an NSSArena upon success
+ */
+
+/*
+ * XXX fgmr
+ * Arenas can be named upon creation; this is mostly of use when
+ * debugging. Should we expose that here, allowing an optional
+ * "const char *name" argument? Should the public version of this
+ * call (NSSArena_Create) have it too?
+ */
+
+NSS_EXTERN NSSArena *
+nssArena_Create
+(
+ void
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+
+/*
+ * nssArena_Destroy
+ *
+ * This routine will destroy the specified arena, freeing all memory
+ * allocated from it. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCESS. If unsuccessful, it will
+ * set an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_EXTERN PRStatus
+nssArena_Destroy
+(
+ NSSArena *arena
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+
+/*
+ * nssArena_Mark
+ *
+ * This routine "marks" the current state of an arena. Space
+ * allocated after the arena has been marked can be freed by
+ * releasing the arena back to the mark with nssArena_Release,
+ * or committed by calling nssArena_Unmark. When successful,
+ * this routine returns a valid nssArenaMark pointer. This
+ * routine may return NULL upon error, in which case it will
+ * have set an error on the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon failure
+ * An nssArenaMark pointer upon success
+ */
+
+NSS_EXTERN nssArenaMark *
+nssArena_Mark
+(
+ NSSArena *arena
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD;
+
+/*
+ * nssArena_Release
+ *
+ * This routine invalidates and releases all memory allocated from
+ * the specified arena after the point at which the specified mark
+ * was obtained. This routine returns a PRStatus value; if successful,
+ * it will return PR_SUCCESS. If unsuccessful, it will set an error
+ * on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_ARENA_MARK
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_EXTERN PRStatus
+nssArena_Release
+(
+ NSSArena *arena,
+ nssArenaMark *arenaMark
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_ARENA_MARK;
+
+/*
+ * nssArena_Unmark
+ *
+ * This routine "commits" the indicated mark and any marks after
+ * it, making them unreleasable. Note that any earlier marks can
+ * still be released, and such a release will invalidate these
+ * later unmarked regions. If an arena is to be safely shared by
+ * more than one thread, all marks must be either released or
+ * unmarked. This routine returns a PRStatus value; if successful,
+ * it will return PR_SUCCESS. If unsuccessful, it will set an error
+ * on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_ARENA_MARK
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_EXTERN PRStatus
+nssArena_Unmark
+(
+ NSSArena *arena,
+ nssArenaMark *arenaMark
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_ARENA_MARK;
+extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD;
+
+#ifdef ARENA_DESTRUCTOR_LIST
+
+/*
+ * nssArena_registerDestructor
+ *
+ * This routine stores a pointer to a callback and an arbitrary
+ * pointer-sized argument in the arena, at the current point in
+ * the mark stack. If the arena is destroyed, or an "earlier"
+ * mark is released, then this destructor will be called at that
+ * time. Note that the destructor will be called with the arena
+ * locked, which means the destructor may free memory in that
+ * arena, but it may not allocate or cause to be allocated any
+ * memory. This callback facility was included to support our
+ * debug-version pointer-tracker feature; overuse runs counter to
+ * the the original intent of arenas. This routine returns a
+ * PRStatus value; if successful, it will return PR_SUCCESS. If
+ * unsuccessful, it will set an error on the error stack and
+ * return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_EXTERN PRStatus
+nssArena_registerDestructor
+(
+ NSSArena *arena,
+ void (*destructor)(void *argument),
+ void *arg
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_NO_MEMORY;
+
+/*
+ * nssArena_deregisterDestructor
+ *
+ * This routine will remove the first destructor in the specified
+ * arena which has the specified destructor and argument values.
+ * The destructor will not be called. This routine returns a
+ * PRStatus value; if successful, it will return PR_SUCCESS. If
+ * unsuccessful, it will set an error on the error stack and
+ * return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NOT_FOUND
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_EXTERN PRStatus
+nssArena_deregisterDestructor
+(
+ NSSArena *arena,
+ void (*destructor)(void *argument),
+ void *arg
+);
+
+extern const NSSError NSS_ERROR_INVALID_ITEM;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_NOT_FOUND;
+
+#endif /* ARENA_DESTRUCTOR_LIST */
+
+/*
+ * nss_ZAlloc
+ *
+ * This routine allocates and zeroes a section of memory of the
+ * size, and returns to the caller a pointer to that memory. If
+ * the optional arena argument is non-null, the memory will be
+ * obtained from that arena; otherwise, the memory will be obtained
+ * from the heap. This routine may return NULL upon error, in
+ * which case it will have set an error upon the error stack. The
+ * value specified for size may be zero; in which case a valid
+ * zero-length block of memory will be allocated. This block may
+ * be expanded by calling nss_ZRealloc.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the new segment of zeroed memory
+ */
+
+NSS_EXTERN void *
+nss_ZAlloc
+(
+ NSSArena *arenaOpt,
+ PRUint32 size
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD;
+
+/*
+ * nss_ZFreeIf
+ *
+ * If the specified pointer is non-null, then the region of memory
+ * to which it points -- which must have been allocated with
+ * nss_ZAlloc -- will be zeroed and released. This routine
+ * returns a PRStatus value; if successful, it will return PR_SUCCESS.
+ * If unsuccessful, it will set an error on the error stack and return
+ * PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_EXTERN PRStatus
+nss_ZFreeIf
+(
+ void *pointer
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nss_ZRealloc
+ *
+ * This routine reallocates a block of memory obtained by calling
+ * nss_ZAlloc or nss_ZRealloc. The portion of memory
+ * between the new and old sizes -- which is either being newly
+ * obtained or released -- is in either case zeroed. This routine
+ * may return NULL upon failure, in which case it will have placed
+ * an error on the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the replacement segment of memory
+ */
+
+NSS_EXTERN void *
+nss_ZRealloc
+(
+ void *pointer,
+ PRUint32 newSize
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD;
+
+/*
+ * nss_ZNEW
+ *
+ * This preprocessor macro will allocate memory for a new object
+ * of the specified type with nss_ZAlloc, and will cast the
+ * return value appropriately. If the optional arena argument is
+ * non-null, the memory will be obtained from that arena; otherwise,
+ * the memory will be obtained from the heap. This routine may
+ * return NULL upon error, in which case it will have set an error
+ * upon the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the new segment of zeroed memory
+ */
+
+/* The following line exceeds 72 characters, but emacs screws up if I split it. */
+#define nss_ZNEW(arenaOpt, type) ((type *)nss_ZAlloc((arenaOpt), sizeof(type)))
+
+/*
+ * nss_ZNEWARRAY
+ *
+ * This preprocessor macro will allocate memory for an array of
+ * new objects, and will cast the return value appropriately.
+ * If the optional arena argument is non-null, the memory will
+ * be obtained from that arena; otherwise, the memory will be
+ * obtained from the heap. This routine may return NULL upon
+ * error, in which case it will have set an error upon the error
+ * stack. The array size may be specified as zero.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the new segment of zeroed memory
+ */
+
+/* The following line exceeds 72 characters, but emacs screws up if I split it. */
+#define nss_ZNEWARRAY(arenaOpt, type, quantity) ((type *)nss_ZAlloc((arenaOpt), sizeof(type) * (quantity)))
+
+/*
+ * nss_ZREALLOCARRAY
+ *
+ * This preprocessor macro will reallocate memory for an array of
+ * new objects, and will cast the return value appropriately.
+ * This routine may return NULL upon error, in which case it will
+ * have set an error upon the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to the replacement segment of memory
+ */
+#define nss_ZREALLOCARRAY(p, type, quantity) ((type *)nss_ZRealloc((p), sizeof(type) * (quantity)))
+
+/*
+ * nssArena_verifyPointer
+ *
+ * This method is only present in debug builds.
+ *
+ * If the specified pointer is a valid pointer to an NSSArena object,
+ * this routine will return PR_SUCCESS. Otherwise, it will put an
+ * error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ *
+ * Return value:
+ * PR_SUCCESS if the pointer is valid
+ * PR_FAILURE if it isn't
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssArena_verifyPointer
+(
+ const NSSArena *arena
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+#endif /* DEBUG */
+
+/*
+ * nssArena_VERIFYPOINTER
+ *
+ * This macro is always available. In debug builds it will call
+ * nssArena_verifyPointer; in non-debug builds, it will merely
+ * check that the pointer is not null. Note that in non-debug
+ * builds it cannot place an error on the error stack.
+ *
+ * Return value:
+ * PR_SUCCESS if the pointer is valid
+ * PR_FAILURE if it isn't
+ */
+
+#ifdef DEBUG
+#define nssArena_VERIFYPOINTER(p) nssArena_verifyPointer(p)
+#else /* DEBUG */
+/* The following line exceeds 72 characters, but emacs screws up if I split it. */
+#define nssArena_VERIFYPOINTER(p) (((NSSArena *)NULL == (p))?PR_FAILURE:PR_SUCCESS)
+#endif /* DEBUG */
+
+/*
+ * Private function to be called by NSS_Shutdown to cleanup nssArena
+ * bookkeeping.
+ */
+extern PRStatus
+nssArena_Shutdown(void);
+
+/*
+ * nssArenaHashAllocOps
+ *
+ * This constant structure contains allocation callbacks designed for
+ * use with the NSPL routine PL_NewHashTable. For example:
+ *
+ * NSSArena *hashTableArena = nssArena_Create();
+ * PLHashTable *t = PL_NewHashTable(n, hasher, key_compare,
+ * value_compare, nssArenaHashAllocOps, hashTableArena);
+ */
+
+NSS_EXTERN_DATA PLHashAllocOps nssArenaHashAllocOps;
+
+/*
+ * The error stack
+ *
+ * The nonpublic methods relating to the error stack are:
+ *
+ * nss_SetError
+ * nss_ClearErrorStack
+ */
+
+/*
+ * nss_SetError
+ *
+ * This routine places a new error code on the top of the calling
+ * thread's error stack. Calling this routine wiht an error code
+ * of zero will clear the error stack.
+ */
+
+NSS_EXTERN void
+nss_SetError
+(
+ PRUint32 error
+);
+
+/*
+ * nss_ClearErrorStack
+ *
+ * This routine clears the calling thread's error stack.
+ */
+
+NSS_EXTERN void
+nss_ClearErrorStack
+(
+ void
+);
+
+/*
+ * nss_DestroyErrorStack
+ *
+ * This routine frees the calling thread's error stack.
+ */
+
+NSS_EXTERN void
+nss_DestroyErrorStack
+(
+ void
+);
+
+/*
+ * NSSItem
+ *
+ * nssItem_Create
+ * nssItem_Duplicate
+ * nssItem_Equal
+ */
+
+NSS_EXTERN NSSItem *
+nssItem_Create
+(
+ NSSArena *arenaOpt,
+ NSSItem *rvOpt,
+ PRUint32 length,
+ const void *data
+);
+
+NSS_EXTERN void
+nssItem_Destroy
+(
+ NSSItem *item
+);
+
+NSS_EXTERN NSSItem *
+nssItem_Duplicate
+(
+ NSSItem *obj,
+ NSSArena *arenaOpt,
+ NSSItem *rvOpt
+);
+
+NSS_EXTERN PRBool
+nssItem_Equal
+(
+ const NSSItem *one,
+ const NSSItem *two,
+ PRStatus *statusOpt
+);
+
+/*
+ * NSSUTF8
+ *
+ * nssUTF8_CaseIgnoreMatch
+ * nssUTF8_Duplicate
+ * nssUTF8_Size
+ * nssUTF8_Length
+ * nssUTF8_CopyIntoFixedBuffer
+ */
+
+/*
+ * nssUTF8_CaseIgnoreMatch
+ *
+ * Returns true if the two UTF8-encoded strings pointed to by the
+ * two specified NSSUTF8 pointers differ only in typcase.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_TRUE if the strings match, ignoring case
+ * PR_FALSE if they don't
+ * PR_FALSE upon error
+ */
+
+NSS_EXTERN PRBool
+nssUTF8_CaseIgnoreMatch
+(
+ const NSSUTF8 *a,
+ const NSSUTF8 *b,
+ PRStatus *statusOpt
+);
+
+/*
+ * nssUTF8_Duplicate
+ *
+ * This routine duplicates the UTF8-encoded string pointed to by the
+ * specified NSSUTF8 pointer. If the optional arenaOpt argument is
+ * not null, the memory required will be obtained from that arena;
+ * otherwise, the memory required will be obtained from the heap.
+ * A pointer to the new string will be returned. In case of error,
+ * an error will be placed on the error stack and NULL will be
+ * returned.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ */
+
+NSS_EXTERN NSSUTF8 *
+nssUTF8_Duplicate
+(
+ const NSSUTF8 *s,
+ NSSArena *arenaOpt
+);
+
+/*
+ * nssUTF8_PrintableMatch
+ *
+ * Returns true if the two Printable strings pointed to by the
+ * two specified NSSUTF8 pointers match when compared with the
+ * rules for Printable String (leading and trailing spaces are
+ * disregarded, extents of whitespace match irregardless of length,
+ * and case is not significant), then PR_TRUE will be returned.
+ * Otherwise, PR_FALSE will be returned. Upon failure, PR_FALSE
+ * will be returned. If the optional statusOpt argument is not
+ * NULL, then PR_SUCCESS or PR_FAILURE will be stored in that
+ * location.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_TRUE if the strings match, ignoring case
+ * PR_FALSE if they don't
+ * PR_FALSE upon error
+ */
+
+NSS_EXTERN PRBool
+nssUTF8_PrintableMatch
+(
+ const NSSUTF8 *a,
+ const NSSUTF8 *b,
+ PRStatus *statusOpt
+);
+
+/*
+ * nssUTF8_Size
+ *
+ * This routine returns the length in bytes (including the terminating
+ * null) of the UTF8-encoded string pointed to by the specified
+ * NSSUTF8 pointer. Zero is returned on error.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_VALUE_TOO_LARGE
+ *
+ * Return value:
+ * nonzero size of the string
+ * 0 on error
+ */
+
+NSS_EXTERN PRUint32
+nssUTF8_Size
+(
+ const NSSUTF8 *s,
+ PRStatus *statusOpt
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_VALUE_TOO_LARGE;
+
+/*
+ * nssUTF8_Length
+ *
+ * This routine returns the length in characters (not including the
+ * terminating null) of the UTF8-encoded string pointed to by the
+ * specified NSSUTF8 pointer.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_VALUE_TOO_LARGE
+ * NSS_ERROR_INVALID_STRING
+ *
+ * Return value:
+ * length of the string (which may be zero)
+ * 0 on error
+ */
+
+NSS_EXTERN PRUint32
+nssUTF8_Length
+(
+ const NSSUTF8 *s,
+ PRStatus *statusOpt
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_VALUE_TOO_LARGE;
+extern const NSSError NSS_ERROR_INVALID_STRING;
+
+/*
+ * nssUTF8_Create
+ *
+ * This routine creates a UTF8 string from a string in some other
+ * format. Some types of string may include embedded null characters,
+ * so for them the length parameter must be used. For string types
+ * that are null-terminated, the length parameter is optional; if it
+ * is zero, it will be ignored. If the optional arena argument is
+ * non-null, the memory used for the new string will be obtained from
+ * that arena, otherwise it will be obtained from the heap. This
+ * routine may return NULL upon error, in which case it will have
+ * placed an error on the error stack.
+ *
+ * The error may be one of the following:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_UNSUPPORTED_TYPE
+ *
+ * Return value:
+ * NULL upon error
+ * A non-null pointer to a new UTF8 string otherwise
+ */
+
+NSS_EXTERN NSSUTF8 *
+nssUTF8_Create
+(
+ NSSArena *arenaOpt,
+ nssStringType type,
+ const void *inputString,
+ PRUint32 size /* in bytes, not characters */
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE;
+
+NSS_EXTERN NSSItem *
+nssUTF8_GetEncoding
+(
+ NSSArena *arenaOpt,
+ NSSItem *rvOpt,
+ nssStringType type,
+ NSSUTF8 *string
+);
+
+/*
+ * nssUTF8_CopyIntoFixedBuffer
+ *
+ * This will copy a UTF8 string into a fixed-length buffer, making
+ * sure that the all characters are valid. Any remaining space will
+ * be padded with the specified ASCII character, typically either
+ * null or space.
+ *
+ * Blah, blah, blah.
+ */
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_INVALID_ARGUMENT;
+
+NSS_EXTERN PRStatus
+nssUTF8_CopyIntoFixedBuffer
+(
+ NSSUTF8 *string,
+ char *buffer,
+ PRUint32 bufferSize,
+ char pad
+);
+
+/*
+ * nssUTF8_Equal
+ *
+ */
+
+NSS_EXTERN PRBool
+nssUTF8_Equal
+(
+ const NSSUTF8 *a,
+ const NSSUTF8 *b,
+ PRStatus *statusOpt
+);
+
+/*
+ * nssList
+ *
+ * The goal is to provide a simple, optionally threadsafe, linked list
+ * class. Since NSS did not seem to use the circularity of PRCList
+ * much before, this provides a list that appears to be a linear,
+ * NULL-terminated list.
+ */
+
+/*
+ * nssList_Create
+ *
+ * If threadsafe is true, the list will be locked during modifications
+ * and traversals.
+ */
+NSS_EXTERN nssList *
+nssList_Create
+(
+ NSSArena *arenaOpt,
+ PRBool threadSafe
+);
+
+/*
+ * nssList_Destroy
+ */
+NSS_EXTERN PRStatus
+nssList_Destroy
+(
+ nssList *list
+);
+
+NSS_EXTERN void
+nssList_Clear
+(
+ nssList *list,
+ nssListElementDestructorFunc destructor
+);
+
+/*
+ * nssList_SetCompareFunction
+ *
+ * By default, two list elements will be compared by comparing their
+ * data pointers. By setting this function, the user can control
+ * how elements are compared.
+ */
+NSS_EXTERN void
+nssList_SetCompareFunction
+(
+ nssList *list,
+ nssListCompareFunc compareFunc
+);
+
+/*
+ * nssList_SetSortFunction
+ *
+ * Sort function to use for an ordered list.
+ */
+NSS_EXTERN void
+nssList_SetSortFunction
+(
+ nssList *list,
+ nssListSortFunc sortFunc
+);
+
+/*
+ * nssList_Add
+ */
+NSS_EXTERN PRStatus
+nssList_Add
+(
+ nssList *list,
+ void *data
+);
+
+/*
+ * nssList_AddUnique
+ *
+ * This will use the compare function to see if the element is already
+ * in the list.
+ */
+NSS_EXTERN PRStatus
+nssList_AddUnique
+(
+ nssList *list,
+ void *data
+);
+
+/*
+ * nssList_Remove
+ *
+ * Uses the compare function to locate the element and remove it.
+ */
+NSS_EXTERN PRStatus
+nssList_Remove(nssList *list, void *data);
+
+/*
+ * nssList_Get
+ *
+ * Uses the compare function to locate an element. Also serves as
+ * nssList_Exists.
+ */
+NSS_EXTERN void *
+nssList_Get
+(
+ nssList *list,
+ void *data
+);
+
+/*
+ * nssList_Count
+ */
+NSS_EXTERN PRUint32
+nssList_Count
+(
+ nssList *list
+);
+
+/*
+ * nssList_GetArray
+ *
+ * Fill rvArray, up to maxElements, with elements in the list. The
+ * array is NULL-terminated, so its allocated size must be maxElements + 1.
+ */
+NSS_EXTERN PRStatus
+nssList_GetArray
+(
+ nssList *list,
+ void **rvArray,
+ PRUint32 maxElements
+);
+
+/*
+ * nssList_CreateIterator
+ *
+ * Create an iterator for list traversal.
+ */
+NSS_EXTERN nssListIterator *
+nssList_CreateIterator
+(
+ nssList *list
+);
+
+NSS_EXTERN nssList *
+nssList_Clone
+(
+ nssList *list
+);
+
+/*
+ * nssListIterator_Destroy
+ */
+NSS_EXTERN void
+nssListIterator_Destroy
+(
+ nssListIterator *iter
+);
+
+/*
+ * nssListIterator_Start
+ *
+ * Begin a list iteration. After this call, if the list is threadSafe,
+ * the list is *locked*.
+ */
+NSS_EXTERN void *
+nssListIterator_Start
+(
+ nssListIterator *iter
+);
+
+/*
+ * nssListIterator_Next
+ *
+ * Continue a list iteration.
+ */
+NSS_EXTERN void *
+nssListIterator_Next
+(
+ nssListIterator *iter
+);
+
+/*
+ * nssListIterator_Finish
+ *
+ * Complete a list iteration. This *must* be called in order for the
+ * lock to be released.
+ */
+NSS_EXTERN PRStatus
+nssListIterator_Finish
+(
+ nssListIterator *iter
+);
+
+/*
+ * nssHash
+ *
+ * nssHash_Create
+ * nssHash_Destroy
+ * nssHash_Add
+ * nssHash_Remove
+ * nssHash_Count
+ * nssHash_Exists
+ * nssHash_Lookup
+ * nssHash_Iterate
+ */
+
+/*
+ * nssHash_Create
+ *
+ */
+
+NSS_EXTERN nssHash *
+nssHash_Create
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets,
+ PLHashFunction keyHash,
+ PLHashComparator keyCompare,
+ PLHashComparator valueCompare
+);
+
+NSS_EXTERN nssHash *
+nssHash_CreatePointer
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets
+);
+
+NSS_EXTERN nssHash *
+nssHash_CreateString
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets
+);
+
+NSS_EXTERN nssHash *
+nssHash_CreateItem
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets
+);
+
+/*
+ * nssHash_Destroy
+ *
+ */
+NSS_EXTERN void
+nssHash_Destroy
+(
+ nssHash *hash
+);
+
+/*
+ * nssHash_Add
+ *
+ */
+
+extern const NSSError NSS_ERROR_HASH_COLLISION;
+
+NSS_EXTERN PRStatus
+nssHash_Add
+(
+ nssHash *hash,
+ const void *key,
+ const void *value
+);
+
+/*
+ * nssHash_Remove
+ *
+ */
+NSS_EXTERN void
+nssHash_Remove
+(
+ nssHash *hash,
+ const void *it
+);
+
+/*
+ * nssHash_Count
+ *
+ */
+NSS_EXTERN PRUint32
+nssHash_Count
+(
+ nssHash *hash
+);
+
+/*
+ * nssHash_Exists
+ *
+ */
+NSS_EXTERN PRBool
+nssHash_Exists
+(
+ nssHash *hash,
+ const void *it
+);
+
+/*
+ * nssHash_Lookup
+ *
+ */
+NSS_EXTERN void *
+nssHash_Lookup
+(
+ nssHash *hash,
+ const void *it
+);
+
+/*
+ * nssHash_Iterate
+ *
+ */
+NSS_EXTERN void
+nssHash_Iterate
+(
+ nssHash *hash,
+ nssHashIterator fcn,
+ void *closure
+);
+
+
+/*
+ * nssPointerTracker
+ *
+ * This type and these methods are only present in debug builds.
+ *
+ * The nonpublic methods relating to this type are:
+ *
+ * nssPointerTracker_initialize
+ * nssPointerTracker_finalize
+ * nssPointerTracker_add
+ * nssPointerTracker_remove
+ * nssPointerTracker_verify
+ */
+
+/*
+ * nssPointerTracker_initialize
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine initializes an nssPointerTracker object. Note that
+ * the object must have been declared *static* to guarantee that it
+ * is in a zeroed state initially. This routine is idempotent, and
+ * may even be safely called by multiple threads simultaneously with
+ * the same argument. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCESS. On failure it will set an
+ * error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssPointerTracker_initialize
+(
+ nssPointerTracker *tracker
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+#endif /* DEBUG */
+
+/*
+ * nssPointerTracker_finalize
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine returns the nssPointerTracker object to the pre-
+ * initialized state, releasing all resources used by the object.
+ * It will *NOT* destroy the objects being tracked by the pointer
+ * (should any remain), and therefore cannot be used to "sweep up"
+ * remaining objects. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCES. On failure it will set an
+ * error on the error stack and return PR_FAILURE. If any objects
+ * remain in the tracker when it is finalized, that will be treated
+ * as an error.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_TRACKER_NOT_EMPTY
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssPointerTracker_finalize
+(
+ nssPointerTracker *tracker
+);
+
+extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY;
+#endif /* DEBUG */
+
+/*
+ * nssPointerTracker_add
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine adds the specified pointer to the nssPointerTracker
+ * object. It should be called in constructor objects to register
+ * new valid objects. The nssPointerTracker is threadsafe, but this
+ * call is not idempotent. This routine returns a PRStatus value;
+ * if successful it will return PR_SUCCESS. On failure it will set
+ * an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_TRACKER_NOT_INITIALIZED
+ * NSS_ERROR_DUPLICATE_POINTER
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssPointerTracker_add
+(
+ nssPointerTracker *tracker,
+ const void *pointer
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED;
+extern const NSSError NSS_ERROR_DUPLICATE_POINTER;
+#endif /* DEBUG */
+
+/*
+ * nssPointerTracker_remove
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine removes the specified pointer from the
+ * nssPointerTracker object. It does not call any destructor for the
+ * object; rather, this should be called from the object's destructor.
+ * The nssPointerTracker is threadsafe, but this call is not
+ * idempotent. This routine returns a PRStatus value; if successful
+ * it will return PR_SUCCESS. On failure it will set an error on the
+ * error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_TRACKER_NOT_INITIALIZED
+ * NSS_ERROR_POINTER_NOT_REGISTERED
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssPointerTracker_remove
+(
+ nssPointerTracker *tracker,
+ const void *pointer
+);
+
+extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED;
+extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED;
+#endif /* DEBUG */
+
+/*
+ * nssPointerTracker_verify
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine verifies that the specified pointer has been registered
+ * with the nssPointerTracker object. The nssPointerTracker object is
+ * threadsafe, and this call may be safely called from multiple threads
+ * simultaneously with the same arguments. This routine returns a
+ * PRStatus value; if the pointer is registered this will return
+ * PR_SUCCESS. Otherwise it will set an error on the error stack and
+ * return PR_FAILURE. Although the error is suitable for leaving on
+ * the stack, callers may wish to augment the information available by
+ * placing a more type-specific error on the stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_POINTER_NOT_REGISTERED
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILRUE
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssPointerTracker_verify
+(
+ nssPointerTracker *tracker,
+ const void *pointer
+);
+
+extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED;
+#endif /* DEBUG */
+
+/*
+ * libc
+ *
+ * nsslibc_memcpy
+ * nsslibc_memset
+ * nsslibc_offsetof
+ */
+
+/*
+ * nsslibc_memcpy
+ *
+ * Errors:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * NULL on error
+ * The destination pointer on success
+ */
+
+NSS_EXTERN void *
+nsslibc_memcpy
+(
+ void *dest,
+ const void *source,
+ PRUint32 n
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nsslibc_memset
+ *
+ * Errors:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * NULL on error
+ * The destination pointer on success
+ */
+
+NSS_EXTERN void *
+nsslibc_memset
+(
+ void *dest,
+ PRUint8 byte,
+ PRUint32 n
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nsslibc_memequal
+ *
+ * Errors:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_TRUE if they match
+ * PR_FALSE if they don't
+ * PR_FALSE upon error
+ */
+
+NSS_EXTERN PRBool
+nsslibc_memequal
+(
+ const void *a,
+ const void *b,
+ PRUint32 len,
+ PRStatus *statusOpt
+);
+
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+#define nsslibc_offsetof(str, memb) ((PRPtrdiff)(&(((str *)0)->memb)))
+
+PR_END_EXTERN_C
+
+#endif /* BASE_H */
diff --git a/mozilla/security/nss/lib/base/baset.h b/mozilla/security/nss/lib/base/baset.h
new file mode 100644
index 0000000..a87887a
--- /dev/null
+++ b/mozilla/security/nss/lib/base/baset.h
@@ -0,0 +1,161 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef BASET_H
+#define BASET_H
+
+#ifdef DEBUG
+static const char BASET_CVS_ID[] = "@(#) $RCSfile: baset.h,v $ $Revision: 1.8 $ $Date: 2005/01/20 02:25:45 $";
+#endif /* DEBUG */
+
+/*
+ * baset.h
+ *
+ * This file contains definitions for the basic types used throughout
+ * nss but not available publicly.
+ */
+
+#ifndef NSSBASET_H
+#include "nssbaset.h"
+#endif /* NSSBASET_H */
+
+#include "plhash.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * nssArenaMark
+ *
+ * This type is used to mark the current state of an NSSArena.
+ */
+
+struct nssArenaMarkStr;
+typedef struct nssArenaMarkStr nssArenaMark;
+
+#ifdef DEBUG
+/*
+ * ARENA_THREADMARK
+ *
+ * Optionally, this arena implementation can be compiled with some
+ * runtime checking enabled, which will catch the situation where
+ * one thread "marks" the arena, another thread allocates memory,
+ * and then the mark is released. Usually this is a surprise to
+ * the second thread, and this leads to weird runtime errors.
+ * Define ARENA_THREADMARK to catch these cases; we define it for all
+ * (internal and external) debug builds.
+ */
+#define ARENA_THREADMARK
+
+/*
+ * ARENA_DESTRUCTOR_LIST
+ *
+ * Unfortunately, our pointer-tracker facility, used in debug
+ * builds to agressively fight invalid pointers, requries that
+ * pointers be deregistered when objects are destroyed. This
+ * conflicts with the standard arena usage where "memory-only"
+ * objects (that don't hold onto resources outside the arena)
+ * can be allocated in an arena, and never destroyed other than
+ * when the arena is destroyed. Therefore we have added a
+ * destructor-registratio facility to our arenas. This was not
+ * a simple decision, since we're getting ever-further away from
+ * the original arena philosophy. However, it was felt that
+ * adding this in debug builds wouldn't be so bad; as it would
+ * discourage them from being used for "serious" purposes.
+ * This facility requires ARENA_THREADMARK to be defined.
+ */
+#ifdef ARENA_THREADMARK
+#define ARENA_DESTRUCTOR_LIST
+#endif /* ARENA_THREADMARK */
+
+#endif /* DEBUG */
+
+typedef struct nssListStr nssList;
+typedef struct nssListIteratorStr nssListIterator;
+typedef PRBool (* nssListCompareFunc)(void *a, void *b);
+typedef PRIntn (* nssListSortFunc)(void *a, void *b);
+typedef void (* nssListElementDestructorFunc)(void *el);
+
+typedef struct nssHashStr nssHash;
+typedef void (PR_CALLBACK *nssHashIterator)(const void *key,
+ void *value,
+ void *arg);
+
+/*
+ * nssPointerTracker
+ *
+ * This type is used in debug builds (both external and internal) to
+ * track our object pointers. Objects of this type must be statically
+ * allocated, which means the structure size must be available to the
+ * compiler. Therefore we must expose the contents of this structure.
+ * But please don't access elements directly; use the accessors.
+ */
+
+#ifdef DEBUG
+struct nssPointerTrackerStr {
+ PRCallOnceType once;
+ PZLock *lock;
+ PLHashTable *table;
+};
+typedef struct nssPointerTrackerStr nssPointerTracker;
+#endif /* DEBUG */
+
+/*
+ * nssStringType
+ *
+ * There are several types of strings in the real world. We try to
+ * use only UTF8 and avoid the rest, but that's not always possible.
+ * So we have a couple converter routines to go to and from the other
+ * string types. We have to be able to specify those string types,
+ * so we have this enumeration.
+ */
+
+enum nssStringTypeEnum {
+ nssStringType_DirectoryString,
+ nssStringType_TeletexString, /* Not "teletext" with trailing 't' */
+ nssStringType_PrintableString,
+ nssStringType_UniversalString,
+ nssStringType_BMPString,
+ nssStringType_UTF8String,
+ nssStringType_PHGString,
+ nssStringType_GeneralString,
+
+ nssStringType_Unknown = -1
+};
+typedef enum nssStringTypeEnum nssStringType;
+
+PR_END_EXTERN_C
+
+#endif /* BASET_H */
diff --git a/mozilla/security/nss/lib/base/config.mk b/mozilla/security/nss/lib/base/config.mk
new file mode 100644
index 0000000..96abc90
--- /dev/null
+++ b/mozilla/security/nss/lib/base/config.mk
@@ -0,0 +1,52 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# 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 the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+CONFIG_CVS_ID = "@(#) $RCSfile: config.mk,v $ $Revision: 1.5 $ $Date: 2005/01/20 02:25:45 $"
+
+ifdef BUILD_IDG
+DEFINES += -DNSSDEBUG
+endif
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
diff --git a/mozilla/security/nss/lib/base/error.c b/mozilla/security/nss/lib/base/error.c
new file mode 100644
index 0000000..a0a3297
--- /dev/null
+++ b/mozilla/security/nss/lib/base/error.c
@@ -0,0 +1,305 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: error.c,v $ $Revision: 1.9 $ $Date: 2008/05/17 03:44:39 $";
+#endif /* DEBUG */
+
+/*
+ * error.c
+ *
+ * This file contains the code implementing the per-thread error
+ * stacks upon which most NSS routines report their errors.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+#include <limits.h> /* for UINT_MAX */
+#include <string.h> /* for memmove */
+
+#define NSS_MAX_ERROR_STACK_COUNT 16 /* error codes */
+
+/*
+ * The stack itself has a header, and a sequence of integers.
+ * The header records the amount of space (as measured in stack
+ * slots) already allocated for the stack, and the count of the
+ * number of records currently being used.
+ */
+
+struct stack_header_str {
+ PRUint16 space;
+ PRUint16 count;
+};
+
+struct error_stack_str {
+ struct stack_header_str header;
+ PRInt32 stack[1];
+};
+typedef struct error_stack_str error_stack;
+
+/*
+ * error_stack_index
+ *
+ * Thread-private data must be indexed. This is that index.
+ * See PR_NewThreadPrivateIndex for more information.
+ *
+ * Thread-private data indexes are in the range [0, 127].
+ */
+
+#define INVALID_TPD_INDEX UINT_MAX
+static PRUintn error_stack_index = INVALID_TPD_INDEX;
+
+/*
+ * call_once
+ *
+ * The thread-private index must be obtained (once!) at runtime.
+ * This block is used for that one-time call.
+ */
+
+static PRCallOnceType error_call_once;
+
+/*
+ * error_once_function
+ *
+ * This is the once-called callback.
+ */
+static PRStatus
+error_once_function ( void)
+{
+ return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
+}
+
+/*
+ * error_get_my_stack
+ *
+ * This routine returns the calling thread's error stack, creating
+ * it if necessary. It may return NULL upon error, which implicitly
+ * means that it ran out of memory.
+ */
+
+static error_stack *
+error_get_my_stack ( void)
+{
+ PRStatus st;
+ error_stack *rv;
+ PRUintn new_size;
+ PRUint32 new_bytes;
+ error_stack *new_stack;
+
+ if( INVALID_TPD_INDEX == error_stack_index ) {
+ st = PR_CallOnce(&error_call_once, error_once_function);
+ if( PR_SUCCESS != st ) {
+ return (error_stack *)NULL;
+ }
+ }
+
+ rv = (error_stack *)PR_GetThreadPrivate(error_stack_index);
+ if( (error_stack *)NULL == rv ) {
+ /* Doesn't exist; create one */
+ new_size = 16;
+ } else if( rv->header.count == rv->header.space &&
+ rv->header.count < NSS_MAX_ERROR_STACK_COUNT ) {
+ /* Too small, expand it */
+ new_size = PR_MIN( rv->header.space * 2, NSS_MAX_ERROR_STACK_COUNT);
+ } else {
+ /* Okay, return it */
+ return rv;
+ }
+
+ new_bytes = (new_size * sizeof(PRInt32)) + sizeof(error_stack);
+ /* Use NSPR's calloc/realloc, not NSS's, to avoid loops! */
+ new_stack = PR_Calloc(1, new_bytes);
+
+ if( (error_stack *)NULL != new_stack ) {
+ if( (error_stack *)NULL != rv ) {
+ (void)nsslibc_memcpy(new_stack,rv,rv->header.space);
+ }
+ new_stack->header.space = new_size;
+ }
+
+ /* Set the value, whether or not the allocation worked */
+ PR_SetThreadPrivate(error_stack_index, new_stack);
+ return new_stack;
+}
+
+/*
+ * The error stack
+ *
+ * The public methods relating to the error stack are:
+ *
+ * NSS_GetError
+ * NSS_GetErrorStack
+ *
+ * The nonpublic methods relating to the error stack are:
+ *
+ * nss_SetError
+ * nss_ClearErrorStack
+ *
+ */
+
+/*
+ * NSS_GetError
+ *
+ * This routine returns the highest-level (most general) error set
+ * by the most recent NSS library routine called by the same thread
+ * calling this routine.
+ *
+ * This routine cannot fail. However, it may return zero, which
+ * indicates that the previous NSS library call did not set an error.
+ *
+ * Return value:
+ * 0 if no error has been set
+ * A nonzero error number
+ */
+
+NSS_IMPLEMENT PRInt32
+NSS_GetError ( void)
+{
+ error_stack *es = error_get_my_stack();
+
+ if( (error_stack *)NULL == es ) {
+ return NSS_ERROR_NO_MEMORY; /* Good guess! */
+ }
+
+ if( 0 == es->header.count ) {
+ return 0;
+ }
+
+ return es->stack[ es->header.count-1 ];
+}
+
+/*
+ * NSS_GetErrorStack
+ *
+ * This routine returns a pointer to an array of integers, containing
+ * the entire sequence or "stack" of errors set by the most recent NSS
+ * library routine called by the same thread calling this routine.
+ * NOTE: the caller DOES NOT OWN the memory pointed to by the return
+ * value. The pointer will remain valid until the calling thread
+ * calls another NSS routine. The lowest-level (most specific) error
+ * is first in the array, and the highest-level is last. The array is
+ * zero-terminated. This routine may return NULL upon error; this
+ * indicates a low-memory situation.
+ *
+ * Return value:
+ * NULL upon error, which is an implied NSS_ERROR_NO_MEMORY
+ * A NON-caller-owned pointer to an array of integers
+ */
+
+NSS_IMPLEMENT PRInt32 *
+NSS_GetErrorStack ( void)
+{
+ error_stack *es = error_get_my_stack();
+
+ if( (error_stack *)NULL == es ) {
+ return (PRInt32 *)NULL;
+ }
+
+ /* Make sure it's terminated */
+ es->stack[ es->header.count ] = 0;
+
+ return es->stack;
+}
+
+/*
+ * nss_SetError
+ *
+ * This routine places a new error code on the top of the calling
+ * thread's error stack. Calling this routine wiht an error code
+ * of zero will clear the error stack.
+ */
+
+NSS_IMPLEMENT void
+nss_SetError ( PRUint32 error)
+{
+ error_stack *es;
+
+ if( 0 == error ) {
+ nss_ClearErrorStack();
+ return;
+ }
+
+ es = error_get_my_stack();
+ if( (error_stack *)NULL == es ) {
+ /* Oh, well. */
+ return;
+ }
+
+ if (es->header.count < es->header.space) {
+ es->stack[ es->header.count++ ] = error;
+ } else {
+ memmove(es->stack, es->stack + 1,
+ (es->header.space - 1) * (sizeof es->stack[0]));
+ es->stack[ es->header.space - 1 ] = error;
+ }
+ return;
+}
+
+/*
+ * nss_ClearErrorStack
+ *
+ * This routine clears the calling thread's error stack.
+ */
+
+NSS_IMPLEMENT void
+nss_ClearErrorStack ( void)
+{
+ error_stack *es = error_get_my_stack();
+ if( (error_stack *)NULL == es ) {
+ /* Oh, well. */
+ return;
+ }
+
+ es->header.count = 0;
+ es->stack[0] = 0;
+ return;
+}
+
+/*
+ * nss_DestroyErrorStack
+ *
+ * This routine frees the calling thread's error stack.
+ */
+
+NSS_IMPLEMENT void
+nss_DestroyErrorStack ( void)
+{
+ if( INVALID_TPD_INDEX != error_stack_index ) {
+ PR_SetThreadPrivate(error_stack_index, NULL);
+ }
+ return;
+}
diff --git a/mozilla/security/nss/lib/base/errorval.c b/mozilla/security/nss/lib/base/errorval.c
new file mode 100644
index 0000000..11767eb
--- /dev/null
+++ b/mozilla/security/nss/lib/base/errorval.c
@@ -0,0 +1,98 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: errorval.c,v $ $Revision: 1.12 $ $Date: 2007/08/09 22:36:15 $";
+#endif /* DEBUG */
+
+/*
+ * errorval.c
+ *
+ * This file contains the actual error constants used in NSS.
+ */
+
+#ifndef NSSBASET_H
+#include "nssbaset.h"
+#endif /* NSSBASET_H */
+
+const NSSError NSS_ERROR_NO_ERROR = 0;
+const NSSError NSS_ERROR_INTERNAL_ERROR = 1;
+const NSSError NSS_ERROR_NO_MEMORY = 2;
+const NSSError NSS_ERROR_INVALID_POINTER = 3;
+const NSSError NSS_ERROR_INVALID_ARENA = 4;
+const NSSError NSS_ERROR_INVALID_ARENA_MARK = 5;
+const NSSError NSS_ERROR_DUPLICATE_POINTER = 6;
+const NSSError NSS_ERROR_POINTER_NOT_REGISTERED = 7;
+const NSSError NSS_ERROR_TRACKER_NOT_EMPTY = 8;
+const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED = 9;
+const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD = 10;
+const NSSError NSS_ERROR_VALUE_TOO_LARGE = 11;
+const NSSError NSS_ERROR_UNSUPPORTED_TYPE = 12;
+const NSSError NSS_ERROR_BUFFER_TOO_SHORT = 13;
+const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT = 14;
+const NSSError NSS_ERROR_INVALID_BASE64 = 15;
+const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT = 16;
+const NSSError NSS_ERROR_INVALID_ITEM = 17;
+const NSSError NSS_ERROR_INVALID_STRING = 18;
+const NSSError NSS_ERROR_INVALID_ASN1ENCODER = 19;
+const NSSError NSS_ERROR_INVALID_ASN1DECODER = 20;
+
+const NSSError NSS_ERROR_INVALID_BER = 21;
+const NSSError NSS_ERROR_INVALID_ATAV = 22;
+const NSSError NSS_ERROR_INVALID_ARGUMENT = 23;
+const NSSError NSS_ERROR_INVALID_UTF8 = 24;
+const NSSError NSS_ERROR_INVALID_NSSOID = 25;
+const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE = 26;
+
+const NSSError NSS_ERROR_NOT_FOUND = 27;
+
+const NSSError NSS_ERROR_INVALID_PASSWORD = 28;
+const NSSError NSS_ERROR_USER_CANCELED = 29;
+
+const NSSError NSS_ERROR_MAXIMUM_FOUND = 30;
+
+const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND = 31;
+
+const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE = 32;
+
+const NSSError NSS_ERROR_HASH_COLLISION = 33;
+const NSSError NSS_ERROR_DEVICE_ERROR = 34;
+const NSSError NSS_ERROR_INVALID_CERTIFICATE = 35;
+const NSSError NSS_ERROR_BUSY = 36;
+const NSSError NSS_ERROR_ALREADY_INITIALIZED = 37;
+
+const NSSError NSS_ERROR_PKCS11 = 38;
+
diff --git a/mozilla/security/nss/lib/base/hash.c b/mozilla/security/nss/lib/base/hash.c
new file mode 100644
index 0000000..389c296
--- /dev/null
+++ b/mozilla/security/nss/lib/base/hash.c
@@ -0,0 +1,409 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: hash.c,v $ $Revision: 1.11 $ $Date: 2008/02/03 01:59:48 $";
+#endif /* DEBUG */
+
+/*
+ * hash.c
+ *
+ * This is merely a couple wrappers around NSPR's PLHashTable, using
+ * the identity hash and arena-aware allocators.
+ * This is a copy of ckfw/hash.c, with modifications to use NSS types
+ * (not Cryptoki types). Would like for this to be a single implementation,
+ * but doesn't seem like it will work.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+#include "prbit.h"
+
+/*
+ * nssHash
+ *
+ * nssHash_Create
+ * nssHash_Destroy
+ * nssHash_Add
+ * nssHash_Remove
+ * nssHash_Count
+ * nssHash_Exists
+ * nssHash_Lookup
+ * nssHash_Iterate
+ */
+
+struct nssHashStr {
+ NSSArena *arena;
+ PRBool i_alloced_arena;
+ PRLock *mutex;
+
+ /*
+ * The invariant that mutex protects is:
+ * The count accurately reflects the hashtable state.
+ */
+
+ PLHashTable *plHashTable;
+ PRUint32 count;
+};
+
+static PLHashNumber
+nss_identity_hash
+(
+ const void *key
+)
+{
+ PRUint32 i = (PRUint32)key;
+ PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32));
+ return (PLHashNumber)i;
+}
+
+static PLHashNumber
+nss_item_hash
+(
+ const void *key
+)
+{
+ unsigned int i;
+ PLHashNumber h;
+ NSSItem *it = (NSSItem *)key;
+ h = 0;
+ for (i=0; i<it->size; i++)
+ h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)it->data)[i];
+ return h;
+}
+
+static int
+nss_compare_items(const void *v1, const void *v2)
+{
+ PRStatus ignore;
+ return (int)nssItem_Equal((NSSItem *)v1, (NSSItem *)v2, &ignore);
+}
+
+/*
+ * nssHash_create
+ *
+ */
+NSS_IMPLEMENT nssHash *
+nssHash_Create
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets,
+ PLHashFunction keyHash,
+ PLHashComparator keyCompare,
+ PLHashComparator valueCompare
+)
+{
+ nssHash *rv;
+ NSSArena *arena;
+ PRBool i_alloced;
+
+#ifdef NSSDEBUG
+ if( arenaOpt && PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (nssHash *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ if (arenaOpt) {
+ arena = arenaOpt;
+ i_alloced = PR_FALSE;
+ } else {
+ arena = nssArena_Create();
+ i_alloced = PR_TRUE;
+ }
+
+ rv = nss_ZNEW(arena, nssHash);
+ if( (nssHash *)NULL == rv ) {
+ goto loser;
+ }
+
+ rv->mutex = PZ_NewLock(nssILockOther);
+ if( (PZLock *)NULL == rv->mutex ) {
+ goto loser;
+ }
+
+ rv->plHashTable = PL_NewHashTable(numBuckets,
+ keyHash, keyCompare, valueCompare,
+ &nssArenaHashAllocOps, arena);
+ if( (PLHashTable *)NULL == rv->plHashTable ) {
+ (void)PZ_DestroyLock(rv->mutex);
+ goto loser;
+ }
+
+ rv->count = 0;
+ rv->arena = arena;
+ rv->i_alloced_arena = i_alloced;
+
+ return rv;
+loser:
+ (void)nss_ZFreeIf(rv);
+ return (nssHash *)NULL;
+}
+
+/*
+ * nssHash_CreatePointer
+ *
+ */
+NSS_IMPLEMENT nssHash *
+nssHash_CreatePointer
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets
+)
+{
+ return nssHash_Create(arenaOpt, numBuckets,
+ nss_identity_hash, PL_CompareValues, PL_CompareValues);
+}
+
+/*
+ * nssHash_CreateString
+ *
+ */
+NSS_IMPLEMENT nssHash *
+nssHash_CreateString
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets
+)
+{
+ return nssHash_Create(arenaOpt, numBuckets,
+ PL_HashString, PL_CompareStrings, PL_CompareStrings);
+}
+
+/*
+ * nssHash_CreateItem
+ *
+ */
+NSS_IMPLEMENT nssHash *
+nssHash_CreateItem
+(
+ NSSArena *arenaOpt,
+ PRUint32 numBuckets
+)
+{
+ return nssHash_Create(arenaOpt, numBuckets,
+ nss_item_hash, nss_compare_items, PL_CompareValues);
+}
+
+/*
+ * nssHash_Destroy
+ *
+ */
+NSS_IMPLEMENT void
+nssHash_Destroy
+(
+ nssHash *hash
+)
+{
+ (void)PZ_DestroyLock(hash->mutex);
+ PL_HashTableDestroy(hash->plHashTable);
+ if (hash->i_alloced_arena) {
+ nssArena_Destroy(hash->arena);
+ } else {
+ nss_ZFreeIf(hash);
+ }
+}
+
+/*
+ * nssHash_Add
+ *
+ */
+NSS_IMPLEMENT PRStatus
+nssHash_Add
+(
+ nssHash *hash,
+ const void *key,
+ const void *value
+)
+{
+ PRStatus error = PR_FAILURE;
+ PLHashEntry *he;
+
+ PZ_Lock(hash->mutex);
+
+ he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
+ if( (PLHashEntry *)NULL == he ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ } else if (he->value != value) {
+ nss_SetError(NSS_ERROR_HASH_COLLISION);
+ } else {
+ hash->count++;
+ error = PR_SUCCESS;
+ }
+
+ (void)PZ_Unlock(hash->mutex);
+
+ return error;
+}
+
+/*
+ * nssHash_Remove
+ *
+ */
+NSS_IMPLEMENT void
+nssHash_Remove
+(
+ nssHash *hash,
+ const void *it
+)
+{
+ PRBool found;
+
+ PZ_Lock(hash->mutex);
+
+ found = PL_HashTableRemove(hash->plHashTable, it);
+ if( found ) {
+ hash->count--;
+ }
+
+ (void)PZ_Unlock(hash->mutex);
+ return;
+}
+
+/*
+ * nssHash_Count
+ *
+ */
+NSS_IMPLEMENT PRUint32
+nssHash_Count
+(
+ nssHash *hash
+)
+{
+ PRUint32 count;
+
+ PZ_Lock(hash->mutex);
+
+ count = hash->count;
+
+ (void)PZ_Unlock(hash->mutex);
+
+ return count;
+}
+
+/*
+ * nssHash_Exists
+ *
+ */
+NSS_IMPLEMENT PRBool
+nssHash_Exists
+(
+ nssHash *hash,
+ const void *it
+)
+{
+ void *value;
+
+ PZ_Lock(hash->mutex);
+
+ value = PL_HashTableLookup(hash->plHashTable, it);
+
+ (void)PZ_Unlock(hash->mutex);
+
+ if( (void *)NULL == value ) {
+ return PR_FALSE;
+ } else {
+ return PR_TRUE;
+ }
+}
+
+/*
+ * nssHash_Lookup
+ *
+ */
+NSS_IMPLEMENT void *
+nssHash_Lookup
+(
+ nssHash *hash,
+ const void *it
+)
+{
+ void *rv;
+
+ PZ_Lock(hash->mutex);
+
+ rv = PL_HashTableLookup(hash->plHashTable, it);
+
+ (void)PZ_Unlock(hash->mutex);
+
+ return rv;
+}
+
+struct arg_str {
+ nssHashIterator fcn;
+ void *closure;
+};
+
+static PRIntn
+nss_hash_enumerator
+(
+ PLHashEntry *he,
+ PRIntn index,
+ void *arg
+)
+{
+ struct arg_str *as = (struct arg_str *)arg;
+ as->fcn(he->key, he->value, as->closure);
+ return HT_ENUMERATE_NEXT;
+}
+
+/*
+ * nssHash_Iterate
+ *
+ * NOTE that the iteration function will be called with the hashtable locked.
+ */
+NSS_IMPLEMENT void
+nssHash_Iterate
+(
+ nssHash *hash,
+ nssHashIterator fcn,
+ void *closure
+)
+{
+ struct arg_str as;
+ as.fcn = fcn;
+ as.closure = closure;
+
+ PZ_Lock(hash->mutex);
+
+ PL_HashTableEnumerateEntries(hash->plHashTable, nss_hash_enumerator, &as);
+
+ (void)PZ_Unlock(hash->mutex);
+
+ return;
+}
diff --git a/mozilla/security/nss/lib/base/hashops.c b/mozilla/security/nss/lib/base/hashops.c
new file mode 100644
index 0000000..b1158da
--- /dev/null
+++ b/mozilla/security/nss/lib/base/hashops.c
@@ -0,0 +1,120 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: hashops.c,v $ $Revision: 1.6 $ $Date: 2005/01/20 02:25:45 $";
+#endif /* DEBUG */
+
+/*
+ * hashops.c
+ *
+ * This file includes a set of PLHashAllocOps that use NSSArenas.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+static void * PR_CALLBACK
+nss_arena_hash_alloc_table
+(
+ void *pool,
+ PRSize size
+)
+{
+ NSSArena *arena = (NSSArena *)NULL;
+
+#ifdef NSSDEBUG
+ if( (void *)NULL != arena ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return (void *)NULL;
+ }
+ }
+#endif /* NSSDEBUG */
+
+ return nss_ZAlloc(arena, size);
+}
+
+static void PR_CALLBACK
+nss_arena_hash_free_table
+(
+ void *pool,
+ void *item
+)
+{
+ (void)nss_ZFreeIf(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+nss_arena_hash_alloc_entry
+(
+ void *pool,
+ const void *key
+)
+{
+ NSSArena *arena = NULL;
+
+#ifdef NSSDEBUG
+ if( (void *)NULL != arena ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
+ return (void *)NULL;
+ }
+ }
+#endif /* NSSDEBUG */
+
+ return nss_ZNEW(arena, PLHashEntry);
+}
+
+static void PR_CALLBACK
+nss_arena_hash_free_entry
+(
+ void *pool,
+ PLHashEntry *he,
+ PRUintn flag
+)
+{
+ if( HT_FREE_ENTRY == flag ) {
+ (void)nss_ZFreeIf(he);
+ }
+}
+
+NSS_IMPLEMENT_DATA PLHashAllocOps
+nssArenaHashAllocOps = {
+ nss_arena_hash_alloc_table,
+ nss_arena_hash_free_table,
+ nss_arena_hash_alloc_entry,
+ nss_arena_hash_free_entry
+};
diff --git a/mozilla/security/nss/lib/base/item.c b/mozilla/security/nss/lib/base/item.c
new file mode 100644
index 0000000..9713f36
--- /dev/null
+++ b/mozilla/security/nss/lib/base/item.c
@@ -0,0 +1,244 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: item.c,v $ $Revision: 1.4 $ $Date: 2005/01/20 02:25:45 $";
+#endif /* DEBUG */
+
+/*
+ * item.c
+ *
+ * This contains some item-manipulation code.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+/*
+ * nssItem_Create
+ *
+ * -- fgmr comments --
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * A pointer to an NSSItem upon success
+ * NULL upon failure
+ */
+
+NSS_IMPLEMENT NSSItem *
+nssItem_Create
+(
+ NSSArena *arenaOpt,
+ NSSItem *rvOpt,
+ PRUint32 length,
+ const void *data
+)
+{
+ NSSItem *rv = (NSSItem *)NULL;
+
+#ifdef DEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSItem *)NULL;
+ }
+ }
+
+ if( (const void *)NULL == data ) {
+ if( length > 0 ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSItem *)NULL;
+ }
+ }
+#endif /* DEBUG */
+
+ if( (NSSItem *)NULL == rvOpt ) {
+ rv = (NSSItem *)nss_ZNEW(arenaOpt, NSSItem);
+ if( (NSSItem *)NULL == rv ) {
+ goto loser;
+ }
+ } else {
+ rv = rvOpt;
+ }
+
+ rv->size = length;
+ rv->data = nss_ZAlloc(arenaOpt, length);
+ if( (void *)NULL == rv->data ) {
+ goto loser;
+ }
+
+ if( length > 0 ) {
+ (void)nsslibc_memcpy(rv->data, data, length);
+ }
+
+ return rv;
+
+ loser:
+ if( rv != rvOpt ) {
+ nss_ZFreeIf(rv);
+ }
+
+ return (NSSItem *)NULL;
+}
+
+NSS_IMPLEMENT void
+nssItem_Destroy
+(
+ NSSItem *item
+)
+{
+ nss_ClearErrorStack();
+
+ nss_ZFreeIf(item->data);
+ nss_ZFreeIf(item);
+
+}
+
+/*
+ * nssItem_Duplicate
+ *
+ * -- fgmr comments --
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
+ * NSS_ERROR_INVALID_ITEM
+ *
+ * Return value:
+ * A pointer to an NSSItem upon success
+ * NULL upon failure
+ */
+
+NSS_IMPLEMENT NSSItem *
+nssItem_Duplicate
+(
+ NSSItem *obj,
+ NSSArena *arenaOpt,
+ NSSItem *rvOpt
+)
+{
+#ifdef DEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSItem *)NULL;
+ }
+ }
+
+ if( (NSSItem *)NULL == obj ) {
+ nss_SetError(NSS_ERROR_INVALID_ITEM);
+ return (NSSItem *)NULL;
+ }
+#endif /* DEBUG */
+
+ return nssItem_Create(arenaOpt, rvOpt, obj->size, obj->data);
+}
+
+#ifdef DEBUG
+/*
+ * nssItem_verifyPointer
+ *
+ * -- fgmr comments --
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ITEM
+ *
+ * Return value:
+ * PR_SUCCESS upon success
+ * PR_FAILURE upon failure
+ */
+
+NSS_IMPLEMENT PRStatus
+nssItem_verifyPointer
+(
+ const NSSItem *item
+)
+{
+ if( ((const NSSItem *)NULL == item) ||
+ (((void *)NULL == item->data) && (item->size > 0)) ) {
+ nss_SetError(NSS_ERROR_INVALID_ITEM);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif /* DEBUG */
+
+/*
+ * nssItem_Equal
+ *
+ * -- fgmr comments --
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ITEM
+ *
+ * Return value:
+ * PR_TRUE if the items are identical
+ * PR_FALSE if they aren't
+ * PR_FALSE upon error
+ */
+
+NSS_IMPLEMENT PRBool
+nssItem_Equal
+(
+ const NSSItem *one,
+ const NSSItem *two,
+ PRStatus *statusOpt
+)
+{
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ if( ((const NSSItem *)NULL == one) && ((const NSSItem *)NULL == two) ) {
+ return PR_TRUE;
+ }
+
+ if( ((const NSSItem *)NULL == one) || ((const NSSItem *)NULL == two) ) {
+ return PR_FALSE;
+ }
+
+ if( one->size != two->size ) {
+ return PR_FALSE;
+ }
+
+ return nsslibc_memequal(one->data, two->data, one->size, statusOpt);
+}
diff --git a/mozilla/security/nss/lib/base/libc.c b/mozilla/security/nss/lib/base/libc.c
new file mode 100644
index 0000000..14d49fd
--- /dev/null
+++ b/mozilla/security/nss/lib/base/libc.c
@@ -0,0 +1,200 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: libc.c,v $ $Revision: 1.3 $ $Date: 2005/01/20 02:25:45 $";
+#endif /* DEBUG */
+
+/*
+ * libc.c
+ *
+ * This file contains our wrappers/reimplementations for "standard"
+ * libc functions. Things like "memcpy." We add to this as we need
+ * it. Oh, and let's keep it in alphabetical order, should it ever
+ * get large. Most string/character stuff should be in utf8.c, not
+ * here. This file (and maybe utf8.c) should be the only ones in
+ * NSS to include files with angle brackets.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+#include <string.h> /* memcpy, memset */
+
+/*
+ * nsslibc_memcpy
+ * nsslibc_memset
+ * nsslibc_offsetof
+ * nsslibc_memequal
+ */
+
+/*
+ * nsslibc_memcpy
+ *
+ * Errors:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * NULL on error
+ * The destination pointer on success
+ */
+
+NSS_IMPLEMENT void *
+nsslibc_memcpy
+(
+ void *dest,
+ const void *source,
+ PRUint32 n
+)
+{
+#ifdef NSSDEBUG
+ if( ((void *)NULL == dest) || ((const void *)NULL == source) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (void *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ return memcpy(dest, source, (size_t)n);
+}
+
+/*
+ * nsslibc_memset
+ *
+ * Errors:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * NULL on error
+ * The destination pointer on success
+ */
+
+NSS_IMPLEMENT void *
+nsslibc_memset
+(
+ void *dest,
+ PRUint8 byte,
+ PRUint32 n
+)
+{
+#ifdef NSSDEBUG
+ if( ((void *)NULL == dest) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (void *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ return memset(dest, (int)byte, (size_t)n);
+}
+
+/*
+ * nsslibc_memequal
+ *
+ * Errors:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_TRUE if they match
+ * PR_FALSE if they don't
+ * PR_FALSE upon error
+ */
+
+NSS_IMPLEMENT PRBool
+nsslibc_memequal
+(
+ const void *a,
+ const void *b,
+ PRUint32 len,
+ PRStatus *statusOpt
+)
+{
+#ifdef NSSDEBUG
+ if( (((void *)NULL == a) || ((void *)NULL == b)) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return PR_FALSE;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ if( 0 == memcmp(a, b, len) ) {
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+/*
+ * nsslibc_memcmp
+ */
+
+NSS_IMPLEMENT PRInt32
+nsslibc_memcmp
+(
+ const void *a,
+ const void *b,
+ PRUint32 len,
+ PRStatus *statusOpt
+)
+{
+ int v;
+
+#ifdef NSSDEBUG
+ if( (((void *)NULL == a) || ((void *)NULL == b)) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return -2;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ v = memcmp(a, b, len);
+ return (PRInt32)v;
+}
+
+/*
+ * offsetof is a preprocessor definition
+ */
diff --git a/mozilla/security/nss/lib/base/list.c b/mozilla/security/nss/lib/base/list.c
new file mode 100644
index 0000000..19ce8b9
--- /dev/null
+++ b/mozilla/security/nss/lib/base/list.c
@@ -0,0 +1,437 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: list.c,v $ $Revision: 1.20 $ $Date: 2006/09/29 20:13:30 $";
+#endif /* DEBUG */
+
+/*
+ * list.c
+ *
+ * This contains the implementation of NSS's thread-safe linked list.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+struct nssListElementStr {
+ PRCList link;
+ void *data;
+};
+
+typedef struct nssListElementStr nssListElement;
+
+struct nssListStr {
+ NSSArena *arena;
+ PZLock *lock;
+ nssListElement *head;
+ PRUint32 count;
+ nssListCompareFunc compareFunc;
+ nssListSortFunc sortFunc;
+ PRBool i_alloced_arena;
+};
+
+struct nssListIteratorStr {
+ PZLock *lock;
+ nssList *list;
+ nssListElement *current;
+};
+
+#define NSSLIST_LOCK_IF(list) \
+ if ((list)->lock) PZ_Lock((list)->lock)
+
+#define NSSLIST_UNLOCK_IF(list) \
+ if ((list)->lock) PZ_Unlock((list)->lock)
+
+static PRBool
+pointer_compare(void *a, void *b)
+{
+ return (PRBool)(a == b);
+}
+
+static nssListElement *
+nsslist_get_matching_element(nssList *list, void *data)
+{
+ PRCList *link;
+ nssListElement *node;
+ node = list->head;
+ if (!node) {
+ return NULL;
+ }
+ link = &node->link;
+ while (node) {
+ /* using a callback slows things down when it's just compare ... */
+ if (list->compareFunc(node->data, data)) {
+ break;
+ }
+ link = &node->link;
+ if (link == PR_LIST_TAIL(&list->head->link)) {
+ node = NULL;
+ break;
+ }
+ node = (nssListElement *)PR_NEXT_LINK(&node->link);
+ }
+ return node;
+}
+
+NSS_IMPLEMENT nssList *
+nssList_Create
+(
+ NSSArena *arenaOpt,
+ PRBool threadSafe
+)
+{
+ NSSArena *arena;
+ nssList *list;
+ PRBool i_alloced;
+ if (arenaOpt) {
+ arena = arenaOpt;
+ i_alloced = PR_FALSE;
+ } else {
+ arena = nssArena_Create();
+ i_alloced = PR_TRUE;
+ }
+ if (!arena) {
+ return (nssList *)NULL;
+ }
+ list = nss_ZNEW(arena, nssList);
+ if (!list) {
+ if (!arenaOpt) {
+ NSSArena_Destroy(arena);
+ }
+ return (nssList *)NULL;
+ }
+ if (threadSafe) {
+ list->lock = PZ_NewLock(nssILockOther);
+ if (!list->lock) {
+ if (arenaOpt) {
+ nss_ZFreeIf(list);
+ } else {
+ NSSArena_Destroy(arena);
+ }
+ return (nssList *)NULL;
+ }
+ }
+ list->arena = arena;
+ list->i_alloced_arena = i_alloced;
+ list->compareFunc = pointer_compare;
+ return list;
+}
+
+NSS_IMPLEMENT PRStatus
+nssList_Destroy(nssList *list)
+{
+ if (!list->i_alloced_arena) {
+ nssList_Clear(list, NULL);
+ }
+ if (list->lock) {
+ (void)PZ_DestroyLock(list->lock);
+ }
+ if (list->i_alloced_arena) {
+ NSSArena_Destroy(list->arena);
+ list = NULL;
+ }
+ nss_ZFreeIf(list);
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT void
+nssList_SetCompareFunction(nssList *list, nssListCompareFunc compareFunc)
+{
+ list->compareFunc = compareFunc;
+}
+
+NSS_IMPLEMENT void
+nssList_SetSortFunction(nssList *list, nssListSortFunc sortFunc)
+{
+ /* XXX if list already has elements, sort them */
+ list->sortFunc = sortFunc;
+}
+
+NSS_IMPLEMENT nssListCompareFunc
+nssList_GetCompareFunction(nssList *list)
+{
+ return list->compareFunc;
+}
+
+NSS_IMPLEMENT void
+nssList_Clear(nssList *list, nssListElementDestructorFunc destructor)
+{
+ PRCList *link;
+ nssListElement *node, *tmp;
+ NSSLIST_LOCK_IF(list);
+ node = list->head;
+ list->head = NULL;
+ while (node && list->count > 0) {
+ if (destructor) (*destructor)(node->data);
+ link = &node->link;
+ tmp = (nssListElement *)PR_NEXT_LINK(link);
+ PR_REMOVE_LINK(link);
+ nss_ZFreeIf(node);
+ node = tmp;
+ --list->count;
+ }
+ NSSLIST_UNLOCK_IF(list);
+}
+
+static PRStatus
+nsslist_add_element(nssList *list, void *data)
+{
+ nssListElement *node = nss_ZNEW(list->arena, nssListElement);
+ if (!node) {
+ return PR_FAILURE;
+ }
+ PR_INIT_CLIST(&node->link);
+ node->data = data;
+ if (list->head) {
+ if (list->sortFunc) {
+ PRCList *link;
+ nssListElement *currNode;
+ currNode = list->head;
+ /* insert in ordered list */
+ while (currNode) {
+ link = &currNode->link;
+ if (list->sortFunc(data, currNode->data) <= 0) {
+ /* new element goes before current node */
+ PR_INSERT_BEFORE(&node->link, link);
+ /* reset head if this is first */
+ if (currNode == list->head) list->head = node;
+ break;
+ }
+ if (link == PR_LIST_TAIL(&list->head->link)) {
+ /* reached end of list, append */
+ PR_INSERT_AFTER(&node->link, link);
+ break;
+ }
+ currNode = (nssListElement *)PR_NEXT_LINK(&currNode->link);
+ }
+ } else {
+ /* not sorting */
+ PR_APPEND_LINK(&node->link, &list->head->link);
+ }
+ } else {
+ list->head = node;
+ }
+ ++list->count;
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRStatus
+nssList_Add(nssList *list, void *data)
+{
+ PRStatus nssrv;
+ NSSLIST_LOCK_IF(list);
+ nssrv = nsslist_add_element(list, data);
+ NSSLIST_UNLOCK_IF(list);
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRStatus
+nssList_AddUnique(nssList *list, void *data)
+{
+ PRStatus nssrv;
+ nssListElement *node;
+ NSSLIST_LOCK_IF(list);
+ node = nsslist_get_matching_element(list, data);
+ if (node) {
+ /* already in, finish */
+ NSSLIST_UNLOCK_IF(list);
+ return PR_SUCCESS;
+ }
+ nssrv = nsslist_add_element(list, data);
+ NSSLIST_UNLOCK_IF(list);
+ return nssrv;
+}
+
+NSS_IMPLEMENT PRStatus
+nssList_Remove(nssList *list, void *data)
+{
+ nssListElement *node;
+ NSSLIST_LOCK_IF(list);
+ node = nsslist_get_matching_element(list, data);
+ if (node) {
+ if (node == list->head) {
+ list->head = (nssListElement *)PR_NEXT_LINK(&node->link);
+ }
+ PR_REMOVE_LINK(&node->link);
+ nss_ZFreeIf(node);
+ if (--list->count == 0) {
+ list->head = NULL;
+ }
+ }
+ NSSLIST_UNLOCK_IF(list);
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT void *
+nssList_Get(nssList *list, void *data)
+{
+ nssListElement *node;
+ NSSLIST_LOCK_IF(list);
+ node = nsslist_get_matching_element(list, data);
+ NSSLIST_UNLOCK_IF(list);
+ return (node) ? node->data : NULL;
+}
+
+NSS_IMPLEMENT PRUint32
+nssList_Count(nssList *list)
+{
+ return list->count;
+}
+
+NSS_IMPLEMENT PRStatus
+nssList_GetArray(nssList *list, void **rvArray, PRUint32 maxElements)
+{
+ nssListElement *node;
+ PRUint32 i = 0;
+ PR_ASSERT(maxElements > 0);
+ node = list->head;
+ if (!node) {
+ return PR_SUCCESS;
+ }
+ NSSLIST_LOCK_IF(list);
+ while (node) {
+ rvArray[i++] = node->data;
+ if (i == maxElements) break;
+ node = (nssListElement *)PR_NEXT_LINK(&node->link);
+ if (node == list->head) {
+ break;
+ }
+ }
+ NSSLIST_UNLOCK_IF(list);
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT nssList *
+nssList_Clone(nssList *list)
+{
+ nssList *rvList;
+ nssListElement *node;
+ rvList = nssList_Create(NULL, (list->lock != NULL));
+ if (!rvList) {
+ return NULL;
+ }
+ NSSLIST_LOCK_IF(list);
+ if (list->count > 0) {
+ node = list->head;
+ while (PR_TRUE) {
+ nssList_Add(rvList, node->data);
+ node = (nssListElement *)PR_NEXT_LINK(&node->link);
+ if (node == list->head) {
+ break;
+ }
+ }
+ }
+ NSSLIST_UNLOCK_IF(list);
+ return rvList;
+}
+
+NSS_IMPLEMENT nssListIterator *
+nssList_CreateIterator(nssList *list)
+{
+ nssListIterator *rvIterator;
+ rvIterator = nss_ZNEW(NULL, nssListIterator);
+ if (!rvIterator) {
+ return NULL;
+ }
+ rvIterator->list = nssList_Clone(list);
+ if (!rvIterator->list) {
+ nss_ZFreeIf(rvIterator);
+ return NULL;
+ }
+ rvIterator->current = rvIterator->list->head;
+ if (list->lock) {
+ rvIterator->lock = PZ_NewLock(nssILockOther);
+ if (!rvIterator->lock) {
+ nssList_Destroy(rvIterator->list);
+ nss_ZFreeIf(rvIterator);
+ rvIterator = NULL;
+ }
+ }
+ return rvIterator;
+}
+
+NSS_IMPLEMENT void
+nssListIterator_Destroy(nssListIterator *iter)
+{
+ if (iter->lock) {
+ (void)PZ_DestroyLock(iter->lock);
+ }
+ nssList_Destroy(iter->list);
+ nss_ZFreeIf(iter);
+}
+
+NSS_IMPLEMENT void *
+nssListIterator_Start(nssListIterator *iter)
+{
+ NSSLIST_LOCK_IF(iter);
+ if (iter->list->count == 0) {
+ return NULL;
+ }
+ iter->current = iter->list->head;
+ return iter->current->data;
+}
+
+NSS_IMPLEMENT void *
+nssListIterator_Next(nssListIterator *iter)
+{
+ nssListElement *node;
+ PRCList *link;
+ if (iter->list->count == 1 || iter->current == NULL) {
+ /* Reached the end of the list. Don't change the state, force to
+ * user to call nssList_Finish to clean up.
+ */
+ return NULL;
+ }
+ node = (nssListElement *)PR_NEXT_LINK(&iter->current->link);
+ link = &node->link;
+ if (link == PR_LIST_TAIL(&iter->list->head->link)) {
+ /* Signal the end of the list. */
+ iter->current = NULL;
+ return node->data;
+ }
+ iter->current = node;
+ return node->data;
+}
+
+NSS_IMPLEMENT PRStatus
+nssListIterator_Finish(nssListIterator *iter)
+{
+ iter->current = iter->list->head;
+ return (iter->lock) ? PZ_Unlock(iter->lock) : PR_SUCCESS;
+}
+
diff --git a/mozilla/security/nss/lib/base/manifest.mn b/mozilla/security/nss/lib/base/manifest.mn
new file mode 100644
index 0000000..e72ffe9
--- /dev/null
+++ b/mozilla/security/nss/lib/base/manifest.mn
@@ -0,0 +1,71 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# 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 the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+MANIFEST_CVS_ID = "@(#) $RCSfile: manifest.mn,v $ $Revision: 1.10 $ $Date: 2007/08/15 15:29:50 $"
+
+CORE_DEPTH = ../../..
+
+PRIVATE_EXPORTS = \
+ baset.h \
+ base.h \
+ $(NULL)
+
+EXPORTS = \
+ nssbaset.h \
+ nssbase.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ arena.c \
+ error.c \
+ errorval.c \
+ hashops.c \
+ libc.c \
+ tracker.c \
+ item.c \
+ utf8.c \
+ list.c \
+ hash.c \
+ $(NULL)
+
+REQUIRES = nspr
+
+LIBRARY_NAME = nssb
+
+# This part of the code, including all sub-dirs, can be optimized for size
+export ALLOW_OPT_CODE_SIZE = 1
diff --git a/mozilla/security/nss/lib/base/nssbase.h b/mozilla/security/nss/lib/base/nssbase.h
new file mode 100644
index 0000000..435952e
--- /dev/null
+++ b/mozilla/security/nss/lib/base/nssbase.h
@@ -0,0 +1,170 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef NSSBASE_H
+#define NSSBASE_H
+
+#ifdef DEBUG
+static const char NSSBASE_CVS_ID[] = "@(#) $RCSfile: nssbase.h,v $ $Revision: 1.3 $ $Date: 2005/01/20 02:25:45 $";
+#endif /* DEBUG */
+
+/*
+ * nssbase.h
+ *
+ * This header file contains the prototypes of the basic public
+ * NSS routines.
+ */
+
+#ifndef NSSBASET_H
+#include "nssbaset.h"
+#endif /* NSSBASET_H */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * NSSArena
+ *
+ * The public methods relating to this type are:
+ *
+ * NSSArena_Create -- constructor
+ * NSSArena_Destroy
+ */
+
+/*
+ * NSSArena_Create
+ *
+ * This routine creates a new memory arena. This routine may return
+ * NULL upon error, in which case it will have created an error stack.
+ *
+ * The top-level error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an NSSArena upon success
+ */
+
+NSS_EXTERN NSSArena *
+NSSArena_Create
+(
+ void
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+
+/*
+ * NSSArena_Destroy
+ *
+ * This routine will destroy the specified arena, freeing all memory
+ * allocated from it. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCESS. If unsuccessful, it will
+ * create an error stack and return PR_FAILURE.
+ *
+ * The top-level error may be one of the following values:
+ * NSS_ERROR_INVALID_ARENA
+ *
+ * Return value:
+ * PR_SUCCESS upon success
+ * PR_FAILURE upon failure
+ */
+
+NSS_EXTERN PRStatus
+NSSArena_Destroy
+(
+ NSSArena *arena
+);
+
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+
+/*
+ * The error stack
+ *
+ * The public methods relating to the error stack are:
+ *
+ * NSS_GetError
+ * NSS_GetErrorStack
+ */
+
+/*
+ * NSS_GetError
+ *
+ * This routine returns the highest-level (most general) error set
+ * by the most recent NSS library routine called by the same thread
+ * calling this routine.
+ *
+ * This routine cannot fail. It may return NSS_ERROR_NO_ERROR, which
+ * indicates that the previous NSS library call did not set an error.
+ *
+ * Return value:
+ * 0 if no error has been set
+ * A nonzero error number
+ */
+
+NSS_EXTERN NSSError
+NSS_GetError
+(
+ void
+);
+
+extern const NSSError NSS_ERROR_NO_ERROR;
+
+/*
+ * NSS_GetErrorStack
+ *
+ * This routine returns a pointer to an array of NSSError values,
+ * containingthe entire sequence or "stack" of errors set by the most
+ * recent NSS library routine called by the same thread calling this
+ * routine. NOTE: the caller DOES NOT OWN the memory pointed to by
+ * the return value. The pointer will remain valid until the calling
+ * thread calls another NSS routine. The lowest-level (most specific)
+ * error is first in the array, and the highest-level is last. The
+ * array is zero-terminated. This routine may return NULL upon error;
+ * this indicates a low-memory situation.
+ *
+ * Return value:
+ * NULL upon error, which is an implied NSS_ERROR_NO_MEMORY
+ * A NON-caller-owned pointer to an array of NSSError values
+ */
+
+NSS_EXTERN NSSError *
+NSS_GetErrorStack
+(
+ void
+);
+
+PR_END_EXTERN_C
+
+#endif /* NSSBASE_H */
diff --git a/mozilla/security/nss/lib/base/nssbaset.h b/mozilla/security/nss/lib/base/nssbaset.h
new file mode 100644
index 0000000..a359b80
--- /dev/null
+++ b/mozilla/security/nss/lib/base/nssbaset.h
@@ -0,0 +1,155 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef NSSBASET_H
+#define NSSBASET_H
+
+#ifdef DEBUG
+static const char NSSBASET_CVS_ID[] = "@(#) $RCSfile: nssbaset.h,v $ $Revision: 1.8 $ $Date: 2009/04/07 23:52:05 $";
+#endif /* DEBUG */
+
+/*
+ * nssbaset.h
+ *
+ * This file contains the most low-level, fundamental public types.
+ */
+
+#include "nspr.h"
+#include "nssilock.h"
+
+/*
+ * NSS_EXTERN, NSS_IMPLEMENT, NSS_EXTERN_DATA, NSS_IMPLEMENT_DATA
+ *
+ * NSS has its own versions of these NSPR macros, in a form which
+ * does not confuse ctags and other related utilities. NSPR
+ * defines these macros to take the type as an argument, because
+ * of certain OS requirements on platforms not supported by NSS.
+ */
+
+#define DUMMY /* dummy */
+#define NSS_EXTERN extern
+#define NSS_EXTERN_DATA extern
+#define NSS_IMPLEMENT
+#define NSS_IMPLEMENT_DATA
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * NSSError
+ *
+ * Calls to NSS routines may result in one or more errors being placed
+ * on the calling thread's "error stack." Every possible error that
+ * may be returned from a function is declared where the function is
+ * prototyped. All errors are of the following type.
+ */
+
+typedef PRInt32 NSSError;
+
+/*
+ * NSSArena
+ *
+ * Arenas are logical sets of heap memory, from which memory may be
+ * allocated. When an arena is destroyed, all memory allocated within
+ * that arena is implicitly freed. These arenas are thread-safe:
+ * an arena pointer may be used by multiple threads simultaneously.
+ * However, as they are not backed by shared memory, they may only be
+ * used within one process.
+ */
+
+struct NSSArenaStr;
+typedef struct NSSArenaStr NSSArena;
+
+/*
+ * NSSItem
+ *
+ * This is the basic type used to refer to an unconstrained datum of
+ * arbitrary size.
+ */
+
+struct NSSItemStr {
+ void *data;
+ PRUint32 size;
+};
+typedef struct NSSItemStr NSSItem;
+
+
+/*
+ * NSSBER
+ *
+ * Data packed according to the Basic Encoding Rules of ASN.1.
+ */
+
+typedef NSSItem NSSBER;
+
+/*
+ * NSSDER
+ *
+ * Data packed according to the Distinguished Encoding Rules of ASN.1;
+ * this form is also known as the Canonical Encoding Rules form (CER).
+ */
+
+typedef NSSBER NSSDER;
+
+/*
+ * NSSBitString
+ *
+ * Some ASN.1 types use "bit strings," which are passed around as
+ * octet strings but whose length is counted in bits. We use this
+ * typedef of NSSItem to point out the occasions when the length
+ * is counted in bits, not octets.
+ */
+
+typedef NSSItem NSSBitString;
+
+/*
+ * NSSUTF8
+ *
+ * Character strings encoded in UTF-8, as defined by RFC 2279.
+ */
+
+typedef char NSSUTF8;
+
+/*
+ * NSSASCII7
+ *
+ * Character strings guaranteed to be 7-bit ASCII.
+ */
+
+typedef char NSSASCII7;
+
+PR_END_EXTERN_C
+
+#endif /* NSSBASET_H */
diff --git a/mozilla/security/nss/lib/base/tracker.c b/mozilla/security/nss/lib/base/tracker.c
new file mode 100644
index 0000000..3e62896
--- /dev/null
+++ b/mozilla/security/nss/lib/base/tracker.c
@@ -0,0 +1,447 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: tracker.c,v $ $Revision: 1.7 $ $Date: 2008/02/23 05:29:24 $";
+#endif /* DEBUG */
+
+/*
+ * tracker.c
+ *
+ * This file contains the code used by the pointer-tracking calls used
+ * in the debug builds to catch bad pointers. The entire contents are
+ * only available in debug builds (both internal and external builds).
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+#ifdef DEBUG
+/*
+ * identity_hash
+ *
+ * This static callback is a PLHashFunction as defined in plhash.h
+ * It merely returns the value of the object pointer as its hash.
+ * There are no possible errors.
+ */
+
+static PLHashNumber PR_CALLBACK
+identity_hash
+(
+ const void *key
+)
+{
+ return (PLHashNumber)key;
+}
+
+/*
+ * trackerOnceFunc
+ *
+ * This function is called once, using the nssCallOnce function above.
+ * It creates a new pointer tracker object; initialising its hash
+ * table and protective lock.
+ */
+
+static PRStatus
+trackerOnceFunc
+(
+ void *arg
+)
+{
+ nssPointerTracker *tracker = (nssPointerTracker *)arg;
+
+ tracker->lock = PZ_NewLock(nssILockOther);
+ if( (PZLock *)NULL == tracker->lock ) {
+ return PR_FAILURE;
+ }
+
+ tracker->table = PL_NewHashTable(0,
+ identity_hash,
+ PL_CompareValues,
+ PL_CompareValues,
+ (PLHashAllocOps *)NULL,
+ (void *)NULL);
+ if( (PLHashTable *)NULL == tracker->table ) {
+ PZ_DestroyLock(tracker->lock);
+ tracker->lock = (PZLock *)NULL;
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssPointerTracker_initialize
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine initializes an nssPointerTracker object. Note that
+ * the object must have been declared *static* to guarantee that it
+ * is in a zeroed state initially. This routine is idempotent, and
+ * may even be safely called by multiple threads simultaneously with
+ * the same argument. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCESS. On failure it will set an
+ * error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssPointerTracker_initialize
+(
+ nssPointerTracker *tracker
+)
+{
+ PRStatus rv = PR_CallOnceWithArg(&tracker->once, trackerOnceFunc, tracker);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ }
+
+ return rv;
+}
+
+#ifdef DONT_DESTROY_EMPTY_TABLES
+/* See same #ifdef below */
+/*
+ * count_entries
+ *
+ * This static routine is a PLHashEnumerator, as defined in plhash.h.
+ * It merely causes the enumeration function to count the number of
+ * entries.
+ */
+
+static PRIntn PR_CALLBACK
+count_entries
+(
+ PLHashEntry *he,
+ PRIntn index,
+ void *arg
+)
+{
+ return HT_ENUMERATE_NEXT;
+}
+#endif /* DONT_DESTROY_EMPTY_TABLES */
+
+/*
+ * zero_once
+ *
+ * This is a guaranteed zeroed once block. It's used to help clear
+ * the tracker.
+ */
+
+static const PRCallOnceType zero_once;
+
+/*
+ * nssPointerTracker_finalize
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine returns the nssPointerTracker object to the pre-
+ * initialized state, releasing all resources used by the object.
+ * It will *NOT* destroy the objects being tracked by the pointer
+ * (should any remain), and therefore cannot be used to "sweep up"
+ * remaining objects. This routine returns a PRStatus value; if
+ * successful, it will return PR_SUCCES. On failure it will set an
+ * error on the error stack and return PR_FAILURE. If any objects
+ * remain in the tracker when it is finalized, that will be treated
+ * as an error.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_TRACKER_NOT_INITIALIZED
+ * NSS_ERROR_TRACKER_NOT_EMPTY
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssPointerTracker_finalize
+(
+ nssPointerTracker *tracker
+)
+{
+ PZLock *lock;
+
+ if( (nssPointerTracker *)NULL == tracker ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FAILURE;
+ }
+
+ if( (PZLock *)NULL == tracker->lock ) {
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ lock = tracker->lock;
+ PZ_Lock(lock);
+
+ if( (PLHashTable *)NULL == tracker->table ) {
+ PZ_Unlock(lock);
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+#ifdef DONT_DESTROY_EMPTY_TABLES
+ /*
+ * I changed my mind; I think we don't want this after all.
+ * Comments?
+ */
+ count = PL_HashTableEnumerateEntries(tracker->table,
+ count_entries,
+ (void *)NULL);
+
+ if( 0 != count ) {
+ PZ_Unlock(lock);
+ nss_SetError(NSS_ERROR_TRACKER_NOT_EMPTY);
+ return PR_FAILURE;
+ }
+#endif /* DONT_DESTROY_EMPTY_TABLES */
+
+ PL_HashTableDestroy(tracker->table);
+ /* memset(tracker, 0, sizeof(nssPointerTracker)); */
+ tracker->once = zero_once;
+ tracker->lock = (PZLock *)NULL;
+ tracker->table = (PLHashTable *)NULL;
+
+ PZ_Unlock(lock);
+ PZ_DestroyLock(lock);
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssPointerTracker_add
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine adds the specified pointer to the nssPointerTracker
+ * object. It should be called in constructor objects to register
+ * new valid objects. The nssPointerTracker is threadsafe, but this
+ * call is not idempotent. This routine returns a PRStatus value;
+ * if successful it will return PR_SUCCESS. On failure it will set
+ * an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_TRACKER_NOT_INITIALIZED
+ * NSS_ERROR_DUPLICATE_POINTER
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssPointerTracker_add
+(
+ nssPointerTracker *tracker,
+ const void *pointer
+)
+{
+ void *check;
+ PLHashEntry *entry;
+
+ if( (nssPointerTracker *)NULL == tracker ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FAILURE;
+ }
+
+ if( (PZLock *)NULL == tracker->lock ) {
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ PZ_Lock(tracker->lock);
+
+ if( (PLHashTable *)NULL == tracker->table ) {
+ PZ_Unlock(tracker->lock);
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ check = PL_HashTableLookup(tracker->table, pointer);
+ if( (void *)NULL != check ) {
+ PZ_Unlock(tracker->lock);
+ nss_SetError(NSS_ERROR_DUPLICATE_POINTER);
+ return PR_FAILURE;
+ }
+
+ entry = PL_HashTableAdd(tracker->table, pointer, (void *)pointer);
+
+ PZ_Unlock(tracker->lock);
+
+ if( (PLHashEntry *)NULL == entry ) {
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssPointerTracker_remove
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine removes the specified pointer from the
+ * nssPointerTracker object. It does not call any destructor for the
+ * object; rather, this should be called from the object's destructor.
+ * The nssPointerTracker is threadsafe, but this call is not
+ * idempotent. This routine returns a PRStatus value; if successful
+ * it will return PR_SUCCESS. On failure it will set an error on the
+ * error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_TRACKER_NOT_INITIALIZED
+ * NSS_ERROR_POINTER_NOT_REGISTERED
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILURE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssPointerTracker_remove
+(
+ nssPointerTracker *tracker,
+ const void *pointer
+)
+{
+ PRBool registered;
+
+ if( (nssPointerTracker *)NULL == tracker ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FAILURE;
+ }
+
+ if( (PZLock *)NULL == tracker->lock ) {
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ PZ_Lock(tracker->lock);
+
+ if( (PLHashTable *)NULL == tracker->table ) {
+ PZ_Unlock(tracker->lock);
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ registered = PL_HashTableRemove(tracker->table, pointer);
+ PZ_Unlock(tracker->lock);
+
+ if( !registered ) {
+ nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssPointerTracker_verify
+ *
+ * This method is only present in debug builds.
+ *
+ * This routine verifies that the specified pointer has been registered
+ * with the nssPointerTracker object. The nssPointerTracker object is
+ * threadsafe, and this call may be safely called from multiple threads
+ * simultaneously with the same arguments. This routine returns a
+ * PRStatus value; if the pointer is registered this will return
+ * PR_SUCCESS. Otherwise it will set an error on the error stack and
+ * return PR_FAILURE. Although the error is suitable for leaving on
+ * the stack, callers may wish to augment the information available by
+ * placing a more type-specific error on the stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_TRACKER_NOT_INITIALIZED
+ * NSS_ERROR_POINTER_NOT_REGISTERED
+ *
+ * Return value:
+ * PR_SUCCESS
+ * PR_FAILRUE
+ */
+
+NSS_IMPLEMENT PRStatus
+nssPointerTracker_verify
+(
+ nssPointerTracker *tracker,
+ const void *pointer
+)
+{
+ void *check;
+
+ if( (nssPointerTracker *)NULL == tracker ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FAILURE;
+ }
+
+ if( (PZLock *)NULL == tracker->lock ) {
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ PZ_Lock(tracker->lock);
+
+ if( (PLHashTable *)NULL == tracker->table ) {
+ PZ_Unlock(tracker->lock);
+ nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
+ return PR_FAILURE;
+ }
+
+ check = PL_HashTableLookup(tracker->table, pointer);
+ PZ_Unlock(tracker->lock);
+
+ if( (void *)NULL == check ) {
+ nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+#endif /* DEBUG */
diff --git a/mozilla/security/nss/lib/base/utf8.c b/mozilla/security/nss/lib/base/utf8.c
new file mode 100644
index 0000000..e850ee8
--- /dev/null
+++ b/mozilla/security/nss/lib/base/utf8.c
@@ -0,0 +1,762 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile: utf8.c,v $ $Revision: 1.7 $ $Date: 2005/01/20 02:25:45 $";
+#endif /* DEBUG */
+
+/*
+ * utf8.c
+ *
+ * This file contains some additional utility routines required for
+ * handling UTF8 strings.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+#include "plstr.h"
+
+/*
+ * NOTES:
+ *
+ * There's an "is hex string" function in pki1/atav.c. If we need
+ * it in more places, pull that one out.
+ */
+
+/*
+ * nssUTF8_CaseIgnoreMatch
+ *
+ * Returns true if the two UTF8-encoded strings pointed to by the
+ * two specified NSSUTF8 pointers differ only in typcase.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_TRUE if the strings match, ignoring case
+ * PR_FALSE if they don't
+ * PR_FALSE upon error
+ */
+
+NSS_IMPLEMENT PRBool
+nssUTF8_CaseIgnoreMatch
+(
+ const NSSUTF8 *a,
+ const NSSUTF8 *b,
+ PRStatus *statusOpt
+)
+{
+#ifdef NSSDEBUG
+ if( ((const NSSUTF8 *)NULL == a) ||
+ ((const NSSUTF8 *)NULL == b) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return PR_FALSE;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ /*
+ * XXX fgmr
+ *
+ * This is, like, so wrong!
+ */
+ if( 0 == PL_strcasecmp((const char *)a, (const char *)b) ) {
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+/*
+ * nssUTF8_PrintableMatch
+ *
+ * Returns true if the two Printable strings pointed to by the
+ * two specified NSSUTF8 pointers match when compared with the
+ * rules for Printable String (leading and trailing spaces are
+ * disregarded, extents of whitespace match irregardless of length,
+ * and case is not significant), then PR_TRUE will be returned.
+ * Otherwise, PR_FALSE will be returned. Upon failure, PR_FALSE
+ * will be returned. If the optional statusOpt argument is not
+ * NULL, then PR_SUCCESS or PR_FAILURE will be stored in that
+ * location.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_TRUE if the strings match, ignoring case
+ * PR_FALSE if they don't
+ * PR_FALSE upon error
+ */
+
+NSS_IMPLEMENT PRBool
+nssUTF8_PrintableMatch
+(
+ const NSSUTF8 *a,
+ const NSSUTF8 *b,
+ PRStatus *statusOpt
+)
+{
+ PRUint8 *c;
+ PRUint8 *d;
+
+#ifdef NSSDEBUG
+ if( ((const NSSUTF8 *)NULL == a) ||
+ ((const NSSUTF8 *)NULL == b) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return PR_FALSE;
+ }
+#endif /* NSSDEBUG */
+
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ c = (PRUint8 *)a;
+ d = (PRUint8 *)b;
+
+ while( ' ' == *c ) {
+ c++;
+ }
+
+ while( ' ' == *d ) {
+ d++;
+ }
+
+ while( ('\0' != *c) && ('\0' != *d) ) {
+ PRUint8 e, f;
+
+ e = *c;
+ f = *d;
+
+ if( ('a' <= e) && (e <= 'z') ) {
+ e -= ('a' - 'A');
+ }
+
+ if( ('a' <= f) && (f <= 'z') ) {
+ f -= ('a' - 'A');
+ }
+
+ if( e != f ) {
+ return PR_FALSE;
+ }
+
+ c++;
+ d++;
+
+ if( ' ' == *c ) {
+ while( ' ' == *c ) {
+ c++;
+ }
+ c--;
+ }
+
+ if( ' ' == *d ) {
+ while( ' ' == *d ) {
+ d++;
+ }
+ d--;
+ }
+ }
+
+ while( ' ' == *c ) {
+ c++;
+ }
+
+ while( ' ' == *d ) {
+ d++;
+ }
+
+ if( *c == *d ) {
+ /* And both '\0', btw */
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+/*
+ * nssUTF8_Duplicate
+ *
+ * This routine duplicates the UTF8-encoded string pointed to by the
+ * specified NSSUTF8 pointer. If the optional arenaOpt argument is
+ * not null, the memory required will be obtained from that arena;
+ * otherwise, the memory required will be obtained from the heap.
+ * A pointer to the new string will be returned. In case of error,
+ * an error will be placed on the error stack and NULL will be
+ * returned.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_NO_MEMORY
+ */
+
+NSS_IMPLEMENT NSSUTF8 *
+nssUTF8_Duplicate
+(
+ const NSSUTF8 *s,
+ NSSArena *arenaOpt
+)
+{
+ NSSUTF8 *rv;
+ PRUint32 len;
+
+#ifdef NSSDEBUG
+ if( (const NSSUTF8 *)NULL == s ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSUTF8 *)NULL;
+ }
+
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSUTF8 *)NULL;
+ }
+ }
+#endif /* NSSDEBUG */
+
+ len = PL_strlen((const char *)s);
+#ifdef PEDANTIC
+ if( '\0' != ((const char *)s)[ len ] ) {
+ /* must have wrapped, e.g., too big for PRUint32 */
+ nss_SetError(NSS_ERROR_NO_MEMORY);
+ return (NSSUTF8 *)NULL;
+ }
+#endif /* PEDANTIC */
+ len++; /* zero termination */
+
+ rv = nss_ZAlloc(arenaOpt, len);
+ if( (void *)NULL == rv ) {
+ return (NSSUTF8 *)NULL;
+ }
+
+ (void)nsslibc_memcpy(rv, s, len);
+ return rv;
+}
+
+/*
+ * nssUTF8_Size
+ *
+ * This routine returns the length in bytes (including the terminating
+ * null) of the UTF8-encoded string pointed to by the specified
+ * NSSUTF8 pointer. Zero is returned on error.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_VALUE_TOO_LARGE
+ *
+ * Return value:
+ * 0 on error
+ * nonzero length of the string.
+ */
+
+NSS_IMPLEMENT PRUint32
+nssUTF8_Size
+(
+ const NSSUTF8 *s,
+ PRStatus *statusOpt
+)
+{
+ PRUint32 sv;
+
+#ifdef NSSDEBUG
+ if( (const NSSUTF8 *)NULL == s ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return 0;
+ }
+#endif /* NSSDEBUG */
+
+ sv = PL_strlen((const char *)s) + 1;
+#ifdef PEDANTIC
+ if( '\0' != ((const char *)s)[ sv-1 ] ) {
+ /* wrapped */
+ nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return 0;
+ }
+#endif /* PEDANTIC */
+
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ return sv;
+}
+
+/*
+ * nssUTF8_Length
+ *
+ * This routine returns the length in characters (not including the
+ * terminating null) of the UTF8-encoded string pointed to by the
+ * specified NSSUTF8 pointer.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_VALUE_TOO_LARGE
+ * NSS_ERROR_INVALID_STRING
+ *
+ * Return value:
+ * length of the string (which may be zero)
+ * 0 on error
+ */
+
+NSS_IMPLEMENT PRUint32
+nssUTF8_Length
+(
+ const NSSUTF8 *s,
+ PRStatus *statusOpt
+)
+{
+ PRUint32 l = 0;
+ const PRUint8 *c = (const PRUint8 *)s;
+
+#ifdef NSSDEBUG
+ if( (const NSSUTF8 *)NULL == s ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ goto loser;
+ }
+#endif /* NSSDEBUG */
+
+ /*
+ * From RFC 2044:
+ *
+ * UCS-4 range (hex.) UTF-8 octet sequence (binary)
+ * 0000 0000-0000 007F 0xxxxxxx
+ * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
+ * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
+ * 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
+ */
+
+ while( 0 != *c ) {
+ PRUint32 incr;
+ if( (*c & 0x80) == 0 ) {
+ incr = 1;
+ } else if( (*c & 0xE0) == 0xC0 ) {
+ incr = 2;
+ } else if( (*c & 0xF0) == 0xE0 ) {
+ incr = 3;
+ } else if( (*c & 0xF8) == 0xF0 ) {
+ incr = 4;
+ } else if( (*c & 0xFC) == 0xF8 ) {
+ incr = 5;
+ } else if( (*c & 0xFE) == 0xFC ) {
+ incr = 6;
+ } else {
+ nss_SetError(NSS_ERROR_INVALID_STRING);
+ goto loser;
+ }
+
+ l += incr;
+
+#ifdef PEDANTIC
+ if( l < incr ) {
+ /* Wrapped-- too big */
+ nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
+ goto loser;
+ }
+
+ {
+ PRUint8 *d;
+ for( d = &c[1]; d < &c[incr]; d++ ) {
+ if( (*d & 0xC0) != 0xF0 ) {
+ nss_SetError(NSS_ERROR_INVALID_STRING);
+ goto loser;
+ }
+ }
+ }
+#endif /* PEDANTIC */
+
+ c += incr;
+ }
+
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_SUCCESS;
+ }
+
+ return l;
+
+ loser:
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+
+ return 0;
+}
+
+
+/*
+ * nssUTF8_Create
+ *
+ * This routine creates a UTF8 string from a string in some other
+ * format. Some types of string may include embedded null characters,
+ * so for them the length parameter must be used. For string types
+ * that are null-terminated, the length parameter is optional; if it
+ * is zero, it will be ignored. If the optional arena argument is
+ * non-null, the memory used for the new string will be obtained from
+ * that arena, otherwise it will be obtained from the heap. This
+ * routine may return NULL upon error, in which case it will have
+ * placed an error on the error stack.
+ *
+ * The error may be one of the following:
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_UNSUPPORTED_TYPE
+ *
+ * Return value:
+ * NULL upon error
+ * A non-null pointer to a new UTF8 string otherwise
+ */
+
+extern const NSSError NSS_ERROR_INTERNAL_ERROR; /* XXX fgmr */
+
+NSS_IMPLEMENT NSSUTF8 *
+nssUTF8_Create
+(
+ NSSArena *arenaOpt,
+ nssStringType type,
+ const void *inputString,
+ PRUint32 size /* in bytes, not characters */
+)
+{
+ NSSUTF8 *rv = NULL;
+
+#ifdef NSSDEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSUTF8 *)NULL;
+ }
+ }
+
+ if( (const void *)NULL == inputString ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSUTF8 *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ switch( type ) {
+ case nssStringType_DirectoryString:
+ /* This is a composite type requiring BER */
+ nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
+ break;
+ case nssStringType_TeletexString:
+ /*
+ * draft-ietf-pkix-ipki-part1-11 says in part:
+ *
+ * In addition, many legacy implementations support names encoded
+ * in the ISO 8859-1 character set (Latin1String) but tag them as
+ * TeletexString. The Latin1String includes characters used in
+ * Western European countries which are not part of the
+ * TeletexString charcter set. Implementations that process
+ * TeletexString SHOULD be prepared to handle the entire ISO
+ * 8859-1 character set.[ISO 8859-1].
+ */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_PrintableString:
+ /*
+ * PrintableString consists of A-Za-z0-9 ,()+,-./:=?
+ * This is a subset of ASCII, which is a subset of UTF8.
+ * So we can just duplicate the string over.
+ */
+
+ if( 0 == size ) {
+ rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt);
+ } else {
+ rv = nss_ZAlloc(arenaOpt, size+1);
+ if( (NSSUTF8 *)NULL == rv ) {
+ return (NSSUTF8 *)NULL;
+ }
+
+ (void)nsslibc_memcpy(rv, inputString, size);
+ }
+
+ break;
+ case nssStringType_UniversalString:
+ /* 4-byte unicode */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_BMPString:
+ /* Base Multilingual Plane of Unicode */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_UTF8String:
+ if( 0 == size ) {
+ rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt);
+ } else {
+ rv = nss_ZAlloc(arenaOpt, size+1);
+ if( (NSSUTF8 *)NULL == rv ) {
+ return (NSSUTF8 *)NULL;
+ }
+
+ (void)nsslibc_memcpy(rv, inputString, size);
+ }
+
+ break;
+ case nssStringType_PHGString:
+ /*
+ * PHGString is an IA5String (with case-insensitive comparisons).
+ * IA5 is ~almost~ ascii; ascii has dollar-sign where IA5 has
+ * currency symbol.
+ */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_GeneralString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ default:
+ nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
+ break;
+ }
+
+ return rv;
+}
+
+NSS_IMPLEMENT NSSItem *
+nssUTF8_GetEncoding
+(
+ NSSArena *arenaOpt,
+ NSSItem *rvOpt,
+ nssStringType type,
+ NSSUTF8 *string
+)
+{
+ NSSItem *rv = (NSSItem *)NULL;
+ PRStatus status = PR_SUCCESS;
+
+#ifdef NSSDEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSItem *)NULL;
+ }
+ }
+
+ if( (NSSUTF8 *)NULL == string ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSItem *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ switch( type ) {
+ case nssStringType_DirectoryString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_TeletexString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_PrintableString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_UniversalString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_BMPString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ case nssStringType_UTF8String:
+ {
+ NSSUTF8 *dup = nssUTF8_Duplicate(string, arenaOpt);
+ if( (NSSUTF8 *)NULL == dup ) {
+ return (NSSItem *)NULL;
+ }
+
+ if( (NSSItem *)NULL == rvOpt ) {
+ rv = nss_ZNEW(arenaOpt, NSSItem);
+ if( (NSSItem *)NULL == rv ) {
+ (void)nss_ZFreeIf(dup);
+ return (NSSItem *)NULL;
+ }
+ } else {
+ rv = rvOpt;
+ }
+
+ rv->data = dup;
+ dup = (NSSUTF8 *)NULL;
+ rv->size = nssUTF8_Size(rv->data, &status);
+ if( (0 == rv->size) && (PR_SUCCESS != status) ) {
+ if( (NSSItem *)NULL == rvOpt ) {
+ (void)nss_ZFreeIf(rv);
+ }
+ return (NSSItem *)NULL;
+ }
+ }
+ break;
+ case nssStringType_PHGString:
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
+ break;
+ default:
+ nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
+ break;
+ }
+
+ return rv;
+}
+
+/*
+ * nssUTF8_CopyIntoFixedBuffer
+ *
+ * This will copy a UTF8 string into a fixed-length buffer, making
+ * sure that the all characters are valid. Any remaining space will
+ * be padded with the specified ASCII character, typically either
+ * null or space.
+ *
+ * Blah, blah, blah.
+ */
+
+NSS_IMPLEMENT PRStatus
+nssUTF8_CopyIntoFixedBuffer
+(
+ NSSUTF8 *string,
+ char *buffer,
+ PRUint32 bufferSize,
+ char pad
+)
+{
+ PRUint32 stringSize = 0;
+
+#ifdef NSSDEBUG
+ if( (char *)NULL == buffer ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FALSE;
+ }
+
+ if( 0 == bufferSize ) {
+ nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
+ return PR_FALSE;
+ }
+
+ if( (pad & 0x80) != 0x00 ) {
+ nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
+ return PR_FALSE;
+ }
+#endif /* NSSDEBUG */
+
+ if( (NSSUTF8 *)NULL == string ) {
+ string = (NSSUTF8 *) "";
+ }
+
+ stringSize = nssUTF8_Size(string, (PRStatus *)NULL);
+ stringSize--; /* don't count the trailing null */
+ if( stringSize > bufferSize ) {
+ PRUint32 bs = bufferSize;
+ (void)nsslibc_memcpy(buffer, string, bufferSize);
+
+ if( ( ((buffer[ bs-1 ] & 0x80) == 0x00)) ||
+ ((bs > 1) && ((buffer[ bs-2 ] & 0xE0) == 0xC0)) ||
+ ((bs > 2) && ((buffer[ bs-3 ] & 0xF0) == 0xE0)) ||
+ ((bs > 3) && ((buffer[ bs-4 ] & 0xF8) == 0xF0)) ||
+ ((bs > 4) && ((buffer[ bs-5 ] & 0xFC) == 0xF8)) ||
+ ((bs > 5) && ((buffer[ bs-6 ] & 0xFE) == 0xFC)) ) {
+ /* It fit exactly */
+ return PR_SUCCESS;
+ }
+
+ /* Too long. We have to trim the last character */
+ for( /*bs*/; bs != 0; bs-- ) {
+ if( (buffer[bs-1] & 0xC0) != 0x80 ) {
+ buffer[bs-1] = pad;
+ break;
+ } else {
+ buffer[bs-1] = pad;
+ }
+ }
+ } else {
+ (void)nsslibc_memset(buffer, pad, bufferSize);
+ (void)nsslibc_memcpy(buffer, string, stringSize);
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssUTF8_Equal
+ *
+ */
+
+NSS_IMPLEMENT PRBool
+nssUTF8_Equal
+(
+ const NSSUTF8 *a,
+ const NSSUTF8 *b,
+ PRStatus *statusOpt
+)
+{
+ PRUint32 la, lb;
+
+#ifdef NSSDEBUG
+ if( ((const NSSUTF8 *)NULL == a) ||
+ ((const NSSUTF8 *)NULL == b) ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ if( (PRStatus *)NULL != statusOpt ) {
+ *statusOpt = PR_FAILURE;
+ }
+ return PR_FALSE;
+ }
+#endif /* NSSDEBUG */
+
+ la = nssUTF8_Size(a, statusOpt);
+ if( 0 == la ) {
+ return PR_FALSE;
+ }
+
+ lb = nssUTF8_Size(b, statusOpt);
+ if( 0 == lb ) {
+ return PR_FALSE;
+ }
+
+ if( la != lb ) {
+ return PR_FALSE;
+ }
+
+ return nsslibc_memequal(a, b, la, statusOpt);
+}