Compare commits

..

2 Commits

Author SHA1 Message Date
pavlov%netscape.com
c45c2db17b new shit
git-svn-id: svn://10.0.0.236/branches/IMGLIB2_NEW@91713 18797224-902f-48f8-a5cc-f745e15eee43
2001-04-08 23:55:33 +00:00
(no author)
ebc0074860 This commit was manufactured by cvs2svn to create branch 'IMGLIB2_NEW'.
git-svn-id: svn://10.0.0.236/branches/IMGLIB2_NEW@91429 18797224-902f-48f8-a5cc-f745e15eee43
2001-04-05 06:02:33 +00:00
142 changed files with 10309 additions and 115159 deletions

View File

@@ -0,0 +1,33 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src decoders
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,32 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = ppm png gif jpeg
include $(topsrcdir)/config/rules.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,323 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.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/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _GIF_H_
#define _GIF_H_
/* gif2.h
The interface for the GIF87/89a decoder.
*/
// List of possible parsing states
typedef enum {
gif_gather,
gif_init, //1
gif_type,
gif_version,
gif_global_header,
gif_global_colormap,
gif_image_start, //6
gif_image_header,
gif_image_colormap,
gif_image_body,
gif_lzw_start,
gif_lzw, //11
gif_sub_block,
gif_extension,
gif_control_extension,
gif_consume_block,
gif_skip_block,
gif_done, //17
gif_oom,
gif_error,
gif_comment_extension,
gif_application_extension,
gif_netscape_extension_block,
gif_consume_netscape_extension,
gif_consume_comment,
gif_delay,
gif_wait_for_buffer_full,
gif_stop_animating //added for animation stop
} gstate;
/* "Disposal" method indicates how the image should be handled in the
framebuffer before the subsequent image is displayed. */
typedef enum
{
DISPOSE_NOT_SPECIFIED = 0,
DISPOSE_KEEP = 1, /* Leave it in the framebuffer */
DISPOSE_OVERWRITE_BGCOLOR = 2, /* Overwrite with background color */
DISPOSE_OVERWRITE_PREVIOUS = 4 /* Save-under */
} gdispose;
/* A RGB triplet representing a single pixel in the image's colormap
(if present.) */
typedef struct _GIF_RGB
{
PRUint8 red, green, blue, pad; /* Windows requires the fourth byte &
many compilers pad it anyway. */
/* XXX: hist_count appears to be unused */
//PRUint16 hist_count; /* Histogram frequency count. */
} GIF_RGB;
/* Colormap information. */
typedef struct _GIF_ColorMap {
int32 num_colors; /* Number of colors in the colormap.
A negative value can be used to denote a
possibly non-unique set. */
GIF_RGB *map; /* Colormap colors. */
PRUint8 *index; /* NULL, if map is in index order. Otherwise
specifies the indices of the map entries. */
void *table; /* Lookup table for this colormap. Private to
the Image Library. */
} GIF_ColorMap;
/* An indexed RGB triplet. */
typedef struct _GIF_IRGB {
PRUint8 index;
PRUint8 red, green, blue;
} GIF_IRGB;
/* A GIF decoder's state */
typedef struct gif_struct {
void* clientptr;
/* Callbacks for this decoder instance*/
int (PR_CALLBACK *GIFCallback_NewPixmap)();
int (PR_CALLBACK *GIFCallback_BeginGIF)(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aLogicalScreenBackgroundRGBIndex);
int (PR_CALLBACK* GIFCallback_EndGIF)(
void* aClientData,
int aAnimationLoopCount);
int (PR_CALLBACK* GIFCallback_BeginImageFrame)(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey);
int (PR_CALLBACK* GIFCallback_EndImageFrame)(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout);
int (PR_CALLBACK* GIFCallback_SetupColorspaceConverter)();
int (PR_CALLBACK* GIFCallback_ResetPalette)();
int (PR_CALLBACK* GIFCallback_InitTransparentPixel)();
int (PR_CALLBACK* GIFCallback_DestroyTransparentPixel)();
int (PR_CALLBACK* GIFCallback_HaveDecodedRow)(
void* aClientData,
PRUint8* aRowBufPtr, /* Pointer to single scanline temporary buffer */
PRUint8* aRGBrowBufPtr,/* Pointer to temporary storage for dithering/mapping */
int aXOffset, /* With respect to GIF logical screen origin */
int aLength, /* Length of the row? */
int aRow, /* Row number? */
int aDuplicateCount, /* Number of times to duplicate the row? */
PRUint8 aDrawMode, /* il_draw_mode */
int aInterlacePass);
int (PR_CALLBACK *GIFCallback_HaveImageAll)(
void* aClientData);
/* Parsing state machine */
gstate state; /* Curent decoder master state */
PRUint8 *hold; /* Accumulation buffer */
int32 hold_size; /* Capacity, in bytes, of accumulation buffer */
PRUint8 *gather_head; /* Next byte to read in accumulation buffer */
int32 gather_request_size; /* Number of bytes to accumulate */
int32 gathered; /* bytes accumulated so far*/
gstate post_gather_state; /* State after requested bytes accumulated */
int32 requested_buffer_fullness; /* For netscape application extension */
/* LZW decoder state machine */
PRUint8 *stack; /* Base of decoder stack */
PRUint8 *stackp; /* Current stack pointer */
PRUint16 *prefix;
PRUint8 *suffix;
int datasize;
int codesize;
int codemask;
int clear_code; /* Codeword used to trigger dictionary reset */
int avail; /* Index of next available slot in dictionary */
int oldcode;
PRUint8 firstchar;
int count; /* Remaining # bytes in sub-block */
int bits; /* Number of unread bits in "datum" */
int32 datum; /* 32-bit input buffer */
/* Output state machine */
int ipass; /* Interlace pass; Ranges 1-4 if interlaced. */
PRUintn rows_remaining; /* Rows remaining to be output */
PRUintn irow; /* Current output row, starting at zero */
PRUint8 *rgbrow; /* Temporary storage for dithering/mapping */
PRUint8 *rowbuf; /* Single scanline temporary buffer */
PRUint8 *rowend; /* Pointer to end of rowbuf */
PRUint8 *rowp; /* Current output pointer */
/* Parameters for image frame currently being decoded*/
PRUintn x_offset, y_offset; /* With respect to "screen" origin */
PRUintn height, width;
PRUintn last_x_offset, last_y_offset; /* With respect to "screen" origin */
PRUintn last_height, last_width;
int interlaced; /* TRUE, if scanlines arrive interlaced order */
int tpixel; /* Index of transparent pixel */
GIF_IRGB* transparent_pixel;
int is_transparent; /* TRUE, if tpixel is valid */
int control_extension; /* TRUE, if image control extension present */
int is_local_colormap_defined;
gdispose disposal_method; /* Restore to background, leave in place, etc.*/
gdispose last_disposal_method;
GIF_RGB *local_colormap; /* Per-image colormap */
int local_colormap_size; /* Size of local colormap array. */
PRUint32 delay_time; /* Display time, in milliseconds,
for this image in a multi-image GIF */
/* Global (multi-image) state */
int screen_bgcolor; /* Logical screen background color */
int version; /* Either 89 for GIF89 or 87 for GIF87 */
PRUintn screen_width; /* Logical screen width & height */
PRUintn screen_height;
GIF_RGB *global_colormap; /* Default colormap if local not supplied */
int global_colormap_size; /* Size of global colormap array. */
int images_decoded; /* Counts images for multi-part GIFs */
int destroy_pending; /* Stream has ended */
int progressive_display; /* If TRUE, do Haeberli interlace hack */
int loop_count; /* Netscape specific extension block to control
the number of animation loops a GIF renders. */
} gif_struct;
/* Create a new gif_struct */
extern PRBool gif_create(gif_struct **gs);
/* These are the APIs that the client calls to intialize,
push data to, and shut down the GIF decoder. */
PRBool GIFInit(
gif_struct* gs,
void* aClientData,
int (*PR_CALLBACK GIFCallback_NewPixmap)(),
int (*PR_CALLBACK GIFCallback_BeginGIF)(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aBackgroundRGBIndex),
int (*PR_CALLBACK GIFCallback_EndGIF)(
void* aClientData,
int aAnimationLoopCount),
int (*PR_CALLBACK GIFCallback_BeginImageFrame)(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey),
int (*PR_CALLBACK GIFCallback_EndImageFrame)(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout),
int (*PR_CALLBACK GIFCallback_SetupColorspaceConverter)(),
int (*PR_CALLBACK GIFCallback_ResetPalette)(),
int (*PR_CALLBACK GIFCallback_InitTransparentPixel)(),
int (*PR_CALLBACK GIFCallback_DestroyTransparentPixel)(),
int (*PR_CALLBACK GIFCallback_HaveDecodedRow)(
void* aClientData,
PRUint8* aRowBufPtr, /* Pointer to single scanline temporary buffer */
PRUint8* aRGBrowBufPtr,/* Pointer to temporary storage for dithering/mapping */
int aXOffset, /* With respect to GIF logical screen origin */
int aLength, /* Length of the row? */
int aRow, /* Row number? */
int aDuplicateCount, /* Number of times to duplicate the row? */
PRUint8 aDrawMode, /* il_draw_mode */
int aInterlacePass),
int (*PR_CALLBACK GIFCallback_HaveImageAll)(
void* aClientData)
);
extern void gif_destroy(gif_struct* aGIFStruct);
int gif_write(gif_struct* aGIFStruct, const PRUint8 * buf, PRUint32 numbytes);
PRUint8 gif_write_ready(gif_struct* aGIFStruct);
extern void gif_complete(gif_struct** aGIFStruct);
extern void gif_delay_time_callback(/* void *closure */);
/* Callback functions that the client must implement and pass in
pointers for during the GIFInit call. These will be called back
when the decoder has a decoded rows, frame size information, etc.*/
/* GIFCallback_LogicalScreenSize is called only once to notify the client
of the logical screen size, which will be the size of the total image. */
typedef int (*PR_CALLBACK BEGINGIF_CALLBACK)(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aLogicalScreenBackgroundRGBIndex);
typedef int (PR_CALLBACK *GIFCallback_EndGIF)(
void* aClientData,
int aAnimationLoopCount);
/* GIFCallback_BeginImageFrame is called at the beginning of each frame of
a GIF.*/
typedef int (PR_CALLBACK *GIFCallback_BeginImageFrame)(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFraqeYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight);
extern int GIFCallback_EndImageFrame(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout); /* Time in milliseconds this frame should be displayed before the next frame.
This information appears in a sub control block, so we don't
transmit it back to the client until we're done with the frame. */
/*
extern int GIFCallback_SetupColorspaceConverter();
extern int GIFCallback_ResetPalette();
extern int GIFCallback_InitTransparentPixel();
extern int GIFCallback_DestroyTransparentPixel();
*/
extern int GIFCallback_HaveDecodedRow();
extern int GIFCallback_HaveImageAll();
#endif

View File

@@ -0,0 +1,42 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imggif
LIBRARY_NAME = imggif
IS_COMPONENT = 1
REQUIRES = xpcom necko layout gfx2 imglib2
CPPSRCS = GIF2.cpp nsGIFDecoder2.cpp nsGIFModule.cpp
EXTRA_DSO_LDOPTS = $(GIF_LIBS) $(ZLIB_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,52 @@
#!nmake
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imggif
LIBRARY_NAME = imggif
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsGIFDecoder2.obj \
.\$(OBJDIR)\GIF2.obj \
.\$(OBJDIR)\nsGIFModule.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,506 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
*/
#include "nsGIFDecoder2.h"
#include "nsIInputStream.h"
#include "nsIComponentManager.h"
#include "nsIImage.h"
#include "nsMemory.h"
#include "imgIContainerObserver.h"
#include "nsRect.h"
//////////////////////////////////////////////////////////////////////
// GIF Decoder Implementation
// This is an adaptor between GIF2 and imgIDecoder
NS_IMPL_ISUPPORTS2(nsGIFDecoder2, imgIDecoder, nsIOutputStream);
nsGIFDecoder2::nsGIFDecoder2()
{
NS_INIT_ISUPPORTS();
mImageFrame = nsnull;
mGIFStruct = nsnull;
mAlphaLine = nsnull;
}
nsGIFDecoder2::~nsGIFDecoder2(void)
{
if (mAlphaLine)
nsMemory::Free(mAlphaLine);
if (mGIFStruct) {
gif_destroy(mGIFStruct);
mGIFStruct = nsnull;
}
}
//******************************************************************************
/** imgIDecoder methods **/
//******************************************************************************
//******************************************************************************
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsGIFDecoder2::Init(imgIRequest *aRequest)
{
mImageRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImageContainer));
/* do gif init stuff */
/* Always decode to 24 bit pixdepth */
PRBool created = gif_create(&mGIFStruct);
NS_ASSERTION(created, "gif_create failed");
// Call GIF decoder init routine
GIFInit(
mGIFStruct,
this,
NewPixmap,
BeginGIF,
EndGIF,
BeginImageFrame,
EndImageFrame,
SetupColorspaceConverter,
ResetPalette,
InitTransparentPixel,
DestroyTransparentPixel,
HaveDecodedRow,
HaveImageAll);
return NS_OK;
}
//******************************************************************************
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsGIFDecoder2::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mImageRequest;
NS_IF_ADDREF(*aRequest);
return NS_OK;
}
//******************************************************************************
/** nsIOutputStream methods **/
//******************************************************************************
//******************************************************************************
/* void close (); */
NS_IMETHODIMP nsGIFDecoder2::Close()
{
if (mGIFStruct) {
gif_destroy(mGIFStruct);
mGIFStruct = nsnull;
}
return NS_OK;
}
//******************************************************************************
/* void flush (); */
NS_IMETHODIMP nsGIFDecoder2::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsGIFDecoder2::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* static callback from nsIInputStream::ReadSegments */
static NS_METHOD ReadDataOut(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount)
{
nsGIFDecoder2 *decoder = NS_STATIC_CAST(nsGIFDecoder2*, closure);
*writeCount = decoder->ProcessData((unsigned char*)fromRawSegment, count);
return NS_OK;
}
//******************************************************************************
PRUint32 nsGIFDecoder2::ProcessData(unsigned char *data, PRUint32 count)
{
// Push the data to the GIF decoder
// First we ask if the gif decoder is ready for more data, and if so, push it.
// In the new decoder, we should always be able to process more data since
// we don't wait to decode each frame in an animation now.
if(gif_write_ready(mGIFStruct)) {
gif_write(mGIFStruct, data, count);
}
return count; // we always consume all the data
}
//******************************************************************************
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsGIFDecoder2::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
inStr->ReadSegments(
ReadDataOut, // Callback
this,
count,
_retval);
// if error
//mRequest->Cancel(NS_BINDING_ABORTED); // XXX is this the correct error ?
return NS_OK;
}
//******************************************************************************
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsGIFDecoder2::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsGIFDecoder2::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
NS_IMETHODIMP nsGIFDecoder2::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsGIFDecoder2::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
NS_IMETHODIMP nsGIFDecoder2::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
// GIF decoder callback methods. Part of pulic API for GIF2
//******************************************************************************
//******************************************************************************
int BeginGIF(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aBackgroundRGBIndex)
{
// copy GIF info into imagelib structs
nsGIFDecoder2 *decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
if (decoder->mObserver)
decoder->mObserver->OnStartDecode(nsnull, nsnull);
decoder->mImageContainer->Init(aLogicalScreenWidth, aLogicalScreenHeight, decoder->mObserver);
if (decoder->mObserver)
decoder->mObserver->OnStartContainer(nsnull, nsnull, decoder->mImageContainer);
return 0;
}
//******************************************************************************
int EndGIF(
void* aClientData,
int aAnimationLoopCount)
{
nsGIFDecoder2 *decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
if (decoder->mObserver) {
decoder->mObserver->OnStopContainer(nsnull, nsnull, decoder->mImageContainer);
decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
decoder->mImageContainer->SetLoopCount(aAnimationLoopCount);
decoder->mImageContainer->DecodingComplete();
return 0;
}
//******************************************************************************
int BeginImageFrame(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey) /* don't have this info yet */
{
nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
decoder->mImageFrame = nsnull; // clear out our current frame reference
decoder->mGIFStruct->x_offset = aFrameXOffset;
decoder->mGIFStruct->y_offset = aFrameYOffset;
decoder->mGIFStruct->width = aFrameWidth;
decoder->mGIFStruct->height = aFrameHeight;
return 0;
}
//******************************************************************************
int EndImageFrame(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout) /* Time this frame should be displayed before the next frame
we can't have this in the image frame init because it doesn't
show up in the GIF frame header, it shows up in a sub control
block.*/
{
nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
// We actually have the timeout information before we get the lzw encoded image
// data, at least according to the spec, but we delay in setting the timeout for
// the image until here to help ensure that we have the whole image frame decoded before
// we go off and try to display another frame.
// XXXXXXXX
// decoder->mImageFrame->SetTimeout(aDelayTimeout);
decoder->mImageContainer->EndFrameDecode(aFrameNumber, aDelayTimeout);
if (decoder->mObserver)
decoder->mObserver->OnStopFrame(nsnull, nsnull, decoder->mImageFrame);
decoder->mImageFrame = nsnull;
return 0;
}
//******************************************************************************
// GIF decoder callback
int HaveImageAll(
void* aClientData)
{
return 0;
}
//******************************************************************************
// GIF decoder callback notification that it has decoded a row
int HaveDecodedRow(
void* aClientData,
PRUint8* aRowBufPtr, // Pointer to single scanline temporary buffer
PRUint8* aRGBrowBufPtr,// Pointer to temporary storage for dithering/mapping
int aXOffset, // With respect to GIF logical screen origin
int aLength, // Length of the row?
int aRowNumber, // Row number?
int aDuplicateCount, // Number of times to duplicate the row?
PRUint8 aDrawMode, // il_draw_mode
int aInterlacePass) // interlace pass (1-4)
{
nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
PRUint32 bpr, abpr;
// We have to delay allocation of the image frame until now because
// we won't have control block info (transparency) until now. The conrol
// block of a GIF stream shows up after the image header since transparency
// is added in GIF89a and control blocks are how the extensions are done.
// How annoying.
if(! decoder->mImageFrame) {
gfx_format format = gfxIFormats::RGB;
if (decoder->mGIFStruct->is_transparent)
format = gfxIFormats::RGB_A1;
#ifdef XP_PC
// XXX this works...
format += 1; // RGB to BGR
#endif
// initalize the frame and append it to the container
decoder->mImageFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
decoder->mImageFrame->Init(
decoder->mGIFStruct->x_offset, decoder->mGIFStruct->y_offset,
decoder->mGIFStruct->width, decoder->mGIFStruct->height, format);
decoder->mImageContainer->AppendFrame(decoder->mImageFrame);
if (decoder->mObserver)
decoder->mObserver->OnStartFrame(nsnull, nsnull, decoder->mImageFrame);
decoder->mImageFrame->GetImageBytesPerRow(&bpr);
decoder->mImageFrame->GetAlphaBytesPerRow(&abpr);
if (format == gfxIFormats::RGB_A1 || format == gfxIFormats::BGR_A1) {
if (decoder->mAlphaLine)
nsMemory::Free(decoder->mAlphaLine);
decoder->mAlphaLine = (PRUint8 *)nsMemory::Alloc(abpr);
}
} else {
decoder->mImageFrame->GetImageBytesPerRow(&bpr);
decoder->mImageFrame->GetAlphaBytesPerRow(&abpr);
}
if (aRowBufPtr) {
nscoord width;
decoder->mImageFrame->GetWidth(&width);
PRUint32 iwidth = width;
gfx_format format;
decoder->mImageFrame->GetFormat(&format);
// XXX map the data into colors
int cmapsize;
GIF_RGB* cmap;
if(decoder->mGIFStruct->local_colormap) {
cmapsize = decoder->mGIFStruct->local_colormap_size;
cmap = decoder->mGIFStruct->local_colormap;
} else {
cmapsize = decoder->mGIFStruct->global_colormap_size;
cmap = decoder->mGIFStruct->global_colormap;
}
PRUint8* rgbRowIndex = aRGBrowBufPtr;
PRUint8* rowBufIndex = aRowBufPtr;
switch (format) {
case gfxIFormats::RGB:
{
while(rowBufIndex != decoder->mGIFStruct->rowend) {
#ifdef XP_MAC
*rgbRowIndex++ = 0; // Mac is always 32bits per pixel, this is pad
#endif
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
++rowBufIndex;
}
decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr, bpr, aRowNumber*bpr);
}
break;
case gfxIFormats::BGR:
{
while(rowBufIndex != decoder->mGIFStruct->rowend) {
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
++rowBufIndex;
}
decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr, bpr, aRowNumber*bpr);
}
break;
case gfxIFormats::RGB_A1:
case gfxIFormats::BGR_A1:
{
memset(aRGBrowBufPtr, 0, bpr);
memset(decoder->mAlphaLine, 0, abpr);
PRUint32 iwidth = (PRUint32)width;
for (PRUint32 x=0; x<iwidth; x++) {
if (*rowBufIndex != decoder->mGIFStruct->tpixel) {
#ifdef XP_PC
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
#else
#ifdef XP_MAC
*rgbRowIndex++ = 0; // Mac is always 32bits per pixel, this is pad
#endif
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
#endif
decoder->mAlphaLine[x>>3] |= 1<<(7-x&0x7);
} else {
#ifdef XP_MAC
rgbRowIndex+=4;
#else
rgbRowIndex+=3;
#endif
}
++rowBufIndex;
}
decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr, bpr, aRowNumber*bpr);
decoder->mImageFrame->SetAlphaData(decoder->mAlphaLine, abpr, aRowNumber*abpr);
}
break;
default:
break;
}
nsRect r(0, aRowNumber, width, 1);
decoder->mObserver->OnDataAvailable(nsnull, nsnull, decoder->mImageFrame, &r);
}
return 0;
}
//******************************************************************************
int ResetPalette()
{
return 0;
}
//******************************************************************************
int SetupColorspaceConverter()
{
return 0;
}
//******************************************************************************
int EndImageFrame()
{
return 0;
}
//******************************************************************************
int NewPixmap()
{
return 0;
}
//******************************************************************************
int InitTransparentPixel()
{
return 0;
}
//******************************************************************************
int DestroyTransparentPixel()
{
return 0;
}

View File

@@ -0,0 +1,114 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
*/
#ifndef _nsGIFDecoder2_h
#define _nsGIFDecoder2_h
#include "nsCOMPtr.h"
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#include "GIF2.h"
#define NS_GIFDECODER2_CID \
{ /* 797bec5a-1dd2-11b2-a7f8-ca397e0179c4 */ \
0x797bec5a, \
0x1dd2, \
0x11b2, \
{0xa7, 0xf8, 0xca, 0x39, 0x7e, 0x01, 0x79, 0xc4} \
}
//////////////////////////////////////////////////////////////////////
// nsGIFDecoder2 Definition
class nsGIFDecoder2 : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsGIFDecoder2();
virtual ~nsGIFDecoder2();
static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_METHOD ProcessData(unsigned char *data, PRUint32 count);
nsCOMPtr<imgIContainer> mImageContainer;
nsCOMPtr<gfxIImageFrame> mImageFrame;
nsCOMPtr<imgIRequest> mImageRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
gif_struct *mGIFStruct;
PRUint8 *mAlphaLine;
};
// static callbacks for the GIF decoder
static int PR_CALLBACK BeginGIF(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aBackgroundRGBIndex);
static int PR_CALLBACK HaveDecodedRow(
void* aClientData,
PRUint8* aRowBufPtr, // Pointer to single scanline temporary buffer
PRUint8* aRGBrowBufPtr,// Pointer to temporary storage for dithering/mapping
int aXOffset, // With respect to GIF logical screen origin
int aLength, // Length of the row?
int aRow, // Row number?
int aDuplicateCount, // Number of times to duplicate the row?
PRUint8 aDrawMode, // il_draw_mode
int aInterlacePass);
static int PR_CALLBACK NewPixmap();
static int PR_CALLBACK EndGIF(
void* aClientData,
int aAnimationLoopCount);
static int PR_CALLBACK BeginImageFrame(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey);
static int PR_CALLBACK EndImageFrame(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout);
static int PR_CALLBACK SetupColorspaceConverter();
static int PR_CALLBACK ResetPalette();
static int PR_CALLBACK InitTransparentPixel();
static int PR_CALLBACK DestroyTransparentPixel();
static int PR_CALLBACK HaveImageAll(
void* aClientData);
#endif

View File

@@ -0,0 +1,41 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
*/
#include "nsGIFDecoder2.h"
#include "nsIComponentManager.h"
#include "nsIGenericFactory.h"
#include "nsISupports.h"
#include "nsCOMPtr.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIFDecoder2)
static nsModuleComponentInfo components[] =
{
{ "GIF Decoder",
NS_GIFDECODER2_CID,
"@mozilla.org/image/decoder;2?type=image/gif",
nsGIFDecoder2Constructor, },
};
NS_IMPL_NSGETMODULE("nsGIFModule2", components)

View File

@@ -0,0 +1,18 @@
?AddRef@nsGIFDecoder2@@UAGKXZ ; 2550
?Release@nsGIFDecoder2@@UAGKXZ ; 2550
?gif_write_ready@@YAEPAUgif_struct@@@Z ; 1624
?ProcessData@nsGIFDecoder2@@QAGIPAEI@Z ; 1624
?gif_write@@YAHPAUgif_struct@@PBEI@Z ; 1624
?WriteFrom@nsGIFDecoder2@@UAGIPAVnsIInputStream@@IPAI@Z ; 1309
?Close@nsGIFDecoder2@@UAGIXZ ; 1275
??_GnsGIFDecoder2@@UAEPAXI@Z ; 1275
??0nsGIFDecoder2@@QAE@XZ ; 1275
??1nsGIFDecoder2@@UAE@XZ ; 1275
?QueryInterface@nsGIFDecoder2@@UAGIABUnsID@@PAPAX@Z ; 1275
?GIFInit@@YAHPAUgif_struct@@PAXP6AHXZP6AH1IIE@ZP6AH1H@ZP6AH1IIIIIPAU_GIF_RGB@@@ZP6AH1II@Z2222P6AH1PAE8HHHHEH@ZP6AH1@Z@Z ; 1275
?Init@nsGIFDecoder2@@UAGIPAVimgIRequest@@@Z ; 1275
?Flush@nsGIFDecoder2@@UAGIXZ ; 1275
?gif_destroy@@YAXPAUgif_struct@@@Z ; 1275
?gif_create@@YAHPAPAUgif_struct@@@Z ; 1275
?il_BACat@@YAPADPAPADIPBDI@Z ; 698
_NSGetModule ; 1

View File

@@ -0,0 +1,378 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIconChannel.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsXPIDLString.h"
#include "nsMimeTypes.h"
#include "nsMemory.h"
#include "nsIStringStream.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsIMimeService.h"
#include "nsCExternalHandlerService.h"
#include "plstr.h"
#include <Files.h>
#include <QuickDraw.h>
// nsIconChannel methods
nsIconChannel::nsIconChannel()
{
NS_INIT_REFCNT();
mStatus = NS_OK;
}
nsIconChannel::~nsIconChannel()
{}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsIconChannel,
nsIChannel,
nsIRequest)
nsresult nsIconChannel::Init(nsIURI* uri)
{
nsresult rv;
NS_ASSERTION(uri, "no uri");
mUrl = uri;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
NS_IMETHODIMP nsIconChannel::GetName(PRUnichar* *result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::IsPending(PRBool *result)
{
NS_NOTREACHED("nsIconChannel::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetStatus(nsresult *status)
{
*status = mStatus;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::Cancel(nsresult status)
{
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
nsresult rv = NS_ERROR_FAILURE;
mStatus = status;
return rv;
}
NS_IMETHODIMP nsIconChannel::Suspend(void)
{
NS_NOTREACHED("nsIconChannel::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::Resume(void)
{
NS_NOTREACHED("nsIconChannel::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsIChannel methods:
NS_IMETHODIMP nsIconChannel::GetOriginalURI(nsIURI* *aURI)
{
*aURI = mOriginalURI ? mOriginalURI : mUrl;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOriginalURI(nsIURI* aURI)
{
mOriginalURI = aURI;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetURI(nsIURI* *aURI)
{
*aURI = mUrl;
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetURI(nsIURI* aURI)
{
mUrl = aURI;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
// get the file name from the url
nsXPIDLCString fileName; // will contain a dummy file we'll use to figure out the type of icon desired.
nsXPIDLCString filePath; // will contain an optional parameter for small vs. large icon. default is small
mUrl->GetHost(getter_Copies(fileName));
nsCOMPtr<nsIURL> url (do_QueryInterface(mUrl));
if (url)
url->GetFileBaseName(getter_Copies(filePath));
nsresult rv = NS_OK;
nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
// extract the extension out of the dummy file so we can look it up in the mime service.
char * chFileName = fileName.get(); // get the underlying buffer
char * fileExtension = PL_strrchr(chFileName, '.');
if (!fileExtension) return NS_ERROR_FAILURE; // no file extension to work from.
// look the file extension up in the registry.
nsCOMPtr<nsIMIMEInfo> mimeInfo;
mimeService->GetFromExtension(fileExtension, getter_AddRefs(mimeInfo));
NS_ENSURE_TRUE(mimeInfo, NS_ERROR_FAILURE);
// get the mac creator and file type for this mime object
PRUint32 macType;
PRUint32 macCreator;
mimeInfo->GetMacType(&macType);
mimeInfo->GetMacCreator(&macCreator);
// get a refernce to the desktop database
DTPBRec pb;
OSErr err = noErr;
memset(&pb, 0, sizeof(DTPBRec));
pb.ioCompletion = nil;
pb.ioVRefNum = 0; // default desktop volume
pb.ioNamePtr = nil;
err = PBDTGetPath(&pb);
if (err != noErr) return NS_ERROR_FAILURE;
pb.ioFileCreator = macCreator;
pb.ioFileType = macType;
pb.ioCompletion = nil;
pb.ioTagInfo = 0;
PRUint32 numPixelsInRow = 0;
if (filePath && !nsCRT::strcmp(filePath, "large"))
{
pb.ioDTReqCount = kLarge8BitIconSize;
pb.ioIconType = kLarge8BitIcon;
numPixelsInRow = 32;
}
else
{
pb.ioDTReqCount = kSmall8BitIconSize;
pb.ioIconType = kSmall8BitIcon;
numPixelsInRow = 16;
}
// allocate a buffer large enough to handle the icon
PRUint8 * bitmapData = (PRUint8 *) nsMemory::Alloc (pb.ioDTReqCount);
pb.ioDTBuffer = (Ptr) bitmapData;
err = PBDTGetIcon(&pb, false);
if (err != noErr) return NS_ERROR_FAILURE; // unable to fetch the icon....
nsCString iconBuffer;
iconBuffer.Assign((char) numPixelsInRow);
iconBuffer.Append((char) numPixelsInRow);
CTabHandle cTabHandle = GetCTable(72);
if (!cTabHandle) return NS_ERROR_FAILURE;
HLock((Handle) cTabHandle);
CTabPtr colTable = *cTabHandle;
RGBColor rgbCol;
PRUint8 redValue, greenValue, blueValue;
for (PRUint32 index = 0; index < pb.ioDTReqCount; index ++)
{
// each byte in bitmapData needs to be converted from an 8 bit system color into
// 24 bit RGB data which our special icon image decoder can understand.
ColorSpec colSpec = colTable->ctTable[ bitmapData[index]];
rgbCol = colSpec.rgb;
redValue = rgbCol.red & 0xff;
greenValue = rgbCol.green & 0xff;
blueValue = rgbCol.blue & 0xff;
// for some reason the image code on the mac expects each RGB pixel value to be padded with a preceding byte.
// so add the padding here....
iconBuffer.Append((char) 0);
iconBuffer.Append((char) redValue);
iconBuffer.Append((char) greenValue);
iconBuffer.Append((char) blueValue);
}
HUnlock((Handle) cTabHandle);
DisposeCTable(cTabHandle);
nsMemory::Free(bitmapData);
// now that the color bitmask is taken care of, we need to do the same thing again for the transparency
// bit mask....
if (filePath && !nsCRT::strcmp(filePath, "large"))
{
pb.ioDTReqCount = kLargeIconSize;
pb.ioIconType = kLargeIcon;
}
else
{
pb.ioDTReqCount = kSmallIconSize;
pb.ioIconType = kSmallIcon;
}
// allocate a buffer large enough to handle the icon
bitmapData = (PRUint8 *) nsMemory::Alloc (pb.ioDTReqCount);
pb.ioDTBuffer = (Ptr) bitmapData;
err = PBDTGetIcon(&pb, false);
PRUint32 index = pb.ioDTReqCount/2;
while (index < pb.ioDTReqCount)
{
iconBuffer.Append((char) bitmapData[index]);
iconBuffer.Append((char) bitmapData[index + 1]);
if (numPixelsInRow == 32)
{
iconBuffer.Append((char) bitmapData[index + 2]);
iconBuffer.Append((char) bitmapData[index + 3]);
index += 4;
}
else
{
iconBuffer.Append((char) 255); // 2 bytes of padding
iconBuffer.Append((char) 255);
index += 2;
}
}
nsMemory::Free(bitmapData);
// turn our nsString into a stream looking object...
aListener->OnStartRequest(this, ctxt);
// turn our string into a stream...
nsCOMPtr<nsISupports> streamSupports;
NS_NewByteInputStream(getter_AddRefs(streamSupports), iconBuffer.get(), iconBuffer.Length());
nsCOMPtr<nsIInputStream> inputStr (do_QueryInterface(streamSupports));
aListener->OnDataAvailable(this, ctxt, inputStr, 0, iconBuffer.Length());
aListener->OnStopRequest(this, ctxt, NS_OK, nsnull);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetLoadAttributes(PRUint32 *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadAttributes(PRUint32 aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetContentType(char* *aContentType)
{
if (!aContentType) return NS_ERROR_NULL_POINTER;
*aContentType = nsCRT::strdup("image/icon");
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::SetContentType(const char *aContentType)
{
//It doesn't make sense to set the content-type on this type
// of channel...
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt32 aContentLength)
{
NS_NOTREACHED("nsIconChannel::SetContentLength");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
*aNotificationCallbacks = mCallbacks.get();
NS_IF_ADDREF(*aNotificationCallbacks);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
*aSecurityInfo = nsnull;
return NS_OK;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconChannel_h___
#define nsIconChannel_h___
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIURI.h"
class nsIconChannel : public nsIChannel
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
nsIconChannel();
virtual ~nsIconChannel();
nsresult Init(nsIURI* uri);
protected:
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
PRUint32 mLoadAttributes;
PRInt32 mContentLength;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsISupports> mOwner;
nsresult mStatus;
};
#endif /* nsIconChannel_h___ */

View File

@@ -0,0 +1,62 @@
#!nmake
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Scott MacGregor <mscott@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
DIR=win
MODULE = imgicon
LIBRARY_NAME = imgicon
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsIconDecoder.obj \
.\$(OBJDIR)\nsIconModule.obj \
.\$(OBJDIR)\nsIconProtocolHandler.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(DIST)\lib\imgiconwin_s.lib \
$(NULL)
WIN_LIBS= shell32.lib
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
-I$(DEPTH)\modules\libpr0n\decoders\icon\win \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,195 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*
*/
#include "nsIconDecoder.h"
#include "nsIInputStream.h"
#include "imgIContainer.h"
#include "imgIContainerObserver.h"
#include "nspr.h"
#include "nsIComponentManager.h"
#include "nsRect.h"
NS_IMPL_THREADSAFE_ADDREF(nsIconDecoder);
NS_IMPL_THREADSAFE_RELEASE(nsIconDecoder);
NS_INTERFACE_MAP_BEGIN(nsIconDecoder)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream)
NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
NS_INTERFACE_MAP_ENTRY(imgIDecoder)
NS_INTERFACE_MAP_END_THREADSAFE
nsIconDecoder::nsIconDecoder()
{
NS_INIT_ISUPPORTS();
}
nsIconDecoder::~nsIconDecoder()
{ }
/** imgIDecoder methods **/
NS_IMETHODIMP nsIconDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImage));
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame) return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP nsIconDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
NS_IMETHODIMP nsIconDecoder::Close()
{
if (mObserver)
{
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
mObserver->OnStopContainer(nsnull, nsnull, mImage);
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
return NS_OK;
}
NS_IMETHODIMP nsIconDecoder::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
nsresult rv;
char *buf = (char *)PR_Malloc(count);
if (!buf) return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
// read the data from the input stram...
PRUint32 readLen;
rv = inStr->Read(buf, count, &readLen);
char *data = buf;
if (NS_FAILED(rv)) return rv;
// since WriteFrom is only called once, go ahead and fire the on start notifications..
mObserver->OnStartDecode(nsnull, nsnull);
PRUint32 i = 0;
// Read size
PRInt32 w, h;
w = data[0];
h = data[1];
data += 2;
readLen -= i + 2;
mImage->Init(w, h, mObserver);
if (mObserver)
mObserver->OnStartContainer(nsnull, nsnull, mImage);
mFrame->Init(0, 0, w, h, gfxIFormats::RGB_A1);
mImage->AppendFrame(mFrame);
if (mObserver)
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
PRUint32 bpr, abpr;
nscoord width, height;
mFrame->GetImageBytesPerRow(&bpr);
mFrame->GetAlphaBytesPerRow(&abpr);
mFrame->GetWidth(&width);
mFrame->GetHeight(&height);
i = 0;
PRInt32 rownum = 0; // XXX this better not have a decimal
PRInt32 wroteLen = 0;
do
{
PRUint8 *line = (PRUint8*)data + i*bpr;
mFrame->SetImageData(line, bpr, (rownum++)*bpr);
nsRect r(0, rownum, width, 1);
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
wroteLen += bpr ;
i++;
} while(rownum < height);
// now we want to send in the alpha data...
for (rownum = 0; rownum < height; rownum ++)
{
PRUint8 * line = (PRUint8*) data + abpr * rownum + height*bpr;
mFrame->SetAlphaData(line, abpr, (rownum)*abpr);
}
PR_FREEIF(buf);
return NS_OK;
}
NS_IMETHODIMP nsIconDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconDecoder_h__
#define nsIconDecoder_h__
#include "imgIDecoder.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#define NS_ICONDECODER_CID \
{ /* FFC08380-256C-11d5-9905-001083010E9B */ \
0xffc08380, \
0x256c, \
0x11d5, \
{ 0x99, 0x5, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b } \
}
//////////////////////////////////////////////////////////////////////////////////////////////
// The icon decoder is a decoder specifically tailored for loading icons
// from the OS. We've defined our own little format to represent these icons
// and this decoder takes that format and converts it into 24-bit RGB with alpha channel
// support. It was modeled a bit off the PPM decoder.
//
// Assumptions about the decoder:
// (1) We receive ALL of the data from the icon channel in one OnDataAvailable call. We don't
// support multiple ODA calls yet.
// (2) the format of the incoming data is as follows:
// The first two bytes contain the width and the height of the icon.
// Followed by 3 bytes per pixel for the color bitmap row after row. (for heigh * width * 3 bytes)
// Followed by bit mask data (used for transparency on the alpha channel).
//
//
//////////////////////////////////////////////////////////////////////////////////////////////
class nsIconDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsIconDecoder();
virtual ~nsIconDecoder();
private:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
};
#endif // nsIconDecoder_h__

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsIconDecoder.h"
#include "nsIconProtocolHandler.h"
// objects that just require generic constructors
/******************************************************************************
* Protocol CIDs
*/
#define NS_ICONPROTOCOL_CID { 0xd0f9db12, 0x249c, 0x11d5, { 0x99, 0x5, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b } }
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIconDecoder)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIconProtocolHandler)
static nsModuleComponentInfo components[] =
{
{ "icon decoder",
NS_ICONDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/icon",
nsIconDecoderConstructor, },
{ "Icon Protocol Handler",
NS_ICONPROTOCOL_CID,
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "icon",
nsIconProtocolHandlerConstructor
}
};
NS_IMPL_NSGETMODULE("nsIconDecoderModule", components)

View File

@@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIconChannel.h"
#include "nsIconProtocolHandler.h"
#include "nsIURL.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kStandardURICID, NS_STANDARDURL_CID);
////////////////////////////////////////////////////////////////////////////////
nsIconProtocolHandler::nsIconProtocolHandler()
{
NS_INIT_REFCNT();
}
nsIconProtocolHandler::~nsIconProtocolHandler()
{}
NS_IMPL_ISUPPORTS2(nsIconProtocolHandler, nsIProtocolHandler, nsISupportsWeakReference)
////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:
NS_IMETHODIMP nsIconProtocolHandler::GetScheme(char* *result)
{
*result = nsCRT::strdup("icon");
if (!*result) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP nsIconProtocolHandler::GetDefaultPort(PRInt32 *result)
{
*result = 0;
return NS_OK;
}
NS_IMETHODIMP nsIconProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, nsIURI **result)
{
nsresult rv;
// no concept of a relative icon url
NS_ASSERTION(!aBaseURI, "base url passed into icon protocol handler");
nsCOMPtr<nsIURI> url = do_CreateInstance(kStandardURICID, &rv);
if (NS_FAILED(rv)) return rv;
rv = url->SetSpec((char*)aSpec);
*result = url;
NS_IF_ADDREF(*result);
return rv;
}
NS_IMETHODIMP nsIconProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result)
{
nsCOMPtr<nsIChannel> channel;
NS_NEWXPCOM(channel, nsIconChannel);
if (channel)
NS_STATIC_CAST(nsIconChannel*,NS_STATIC_CAST(nsIChannel*, channel))->Init(url);
*result = channel;
NS_IF_ADDREF(*result);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconProtocolHandler_h___
#define nsIconProtocolHandler_h___
#include "nsWeakReference.h"
#include "nsIProtocolHandler.h"
class nsIconProtocolHandler : public nsIProtocolHandler, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
// nsIconProtocolHandler methods:
nsIconProtocolHandler();
virtual ~nsIconProtocolHandler();
protected:
};
#endif /* nsIconProtocolHandler_h___ */

View File

@@ -0,0 +1,46 @@
#!gmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Scott MacGregor <mscott@netscape.com>
DEPTH=..\..\..\..\..
MODULE=imgicon
LIBRARY_NAME=imgiconwin_s
CPP_OBJS=\
.\$(OBJDIR)\nsIconChannel.obj \
$(NULL)
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
-I..\ \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,377 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIconChannel.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsXPIDLString.h"
#include "nsMimeTypes.h"
#include "nsMemory.h"
#include "nsIStringStream.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
// we need windows.h to read out registry information...
#include <windows.h>
#include <shellapi.h>
// nsIconChannel methods
nsIconChannel::nsIconChannel()
{
NS_INIT_REFCNT();
mStatus = NS_OK;
}
nsIconChannel::~nsIconChannel()
{}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsIconChannel,
nsIChannel,
nsIRequest)
nsresult nsIconChannel::Init(nsIURI* uri)
{
nsresult rv;
NS_ASSERTION(uri, "no uri");
mUrl = uri;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
NS_IMETHODIMP nsIconChannel::GetName(PRUnichar* *result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::IsPending(PRBool *result)
{
NS_NOTREACHED("nsIconChannel::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetStatus(nsresult *status)
{
*status = mStatus;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::Cancel(nsresult status)
{
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
nsresult rv = NS_ERROR_FAILURE;
mStatus = status;
return rv;
}
NS_IMETHODIMP nsIconChannel::Suspend(void)
{
NS_NOTREACHED("nsIconChannel::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::Resume(void)
{
NS_NOTREACHED("nsIconChannel::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsIChannel methods:
NS_IMETHODIMP nsIconChannel::GetOriginalURI(nsIURI* *aURI)
{
*aURI = mOriginalURI ? mOriginalURI : mUrl;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOriginalURI(nsIURI* aURI)
{
mOriginalURI = aURI;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetURI(nsIURI* *aURI)
{
*aURI = mUrl;
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetURI(nsIURI* aURI)
{
mUrl = aURI;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_FAILURE;
}
void InvertRows(unsigned char * aInitialBuffer, PRUint32 sizeOfBuffer, PRUint32 numBytesPerRow)
{
PRUint32 numRows = sizeOfBuffer / numBytesPerRow;
void * temporaryRowHolder = (void *) nsMemory::Alloc(numBytesPerRow);
PRUint32 currentRow = 0;
PRUint32 lastRow = (numRows - 1) * numBytesPerRow;
while (currentRow < lastRow)
{
// store the current row into a temporary buffer
nsCRT::memcpy(temporaryRowHolder, (void *) &aInitialBuffer[currentRow], numBytesPerRow);
nsCRT::memcpy((void *) &aInitialBuffer[currentRow], (void *)&aInitialBuffer[lastRow], numBytesPerRow);
nsCRT::memcpy((void *) &aInitialBuffer[lastRow], temporaryRowHolder, numBytesPerRow);
lastRow -= numBytesPerRow;
currentRow += numBytesPerRow;
}
}
NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
// get the file name from the url
nsXPIDLCString fileName; // will contain a dummy file we'll use to figure out the type of icon desired.
nsXPIDLCString filePath; // will contain an optional parameter for small vs. large icon. default is small
mUrl->GetHost(getter_Copies(fileName));
nsCOMPtr<nsIURL> url (do_QueryInterface(mUrl));
if (url)
url->GetFileBaseName(getter_Copies(filePath));
// 1) get a hIcon for the file.
SHFILEINFO sfi;
UINT infoFlags = SHGFI_USEFILEATTRIBUTES | SHGFI_ICON;
if (filePath && !nsCRT::strcmp(filePath, "large"))
infoFlags |= SHGFI_LARGEICON;
else // default to small
infoFlags |= SHGFI_SMALLICON;
LONG result= SHGetFileInfo(fileName, FILE_ATTRIBUTE_ARCHIVE, &sfi, sizeof(sfi), infoFlags);
if (result > 0 && sfi.hIcon)
{
// we got a handle to an icon. Now we want to get a bitmap for the icon using GetIconInfo....
ICONINFO pIconInfo;
result = GetIconInfo(sfi.hIcon, &pIconInfo);
if (result > 0)
{
// now we have the bit map we need to get info about the bitmap
BITMAPINFO pBitMapInfo;
BITMAPINFOHEADER pBitMapInfoHeader;
pBitMapInfo.bmiHeader.biBitCount = 0;
pBitMapInfo.bmiHeader.biSize = sizeof(pBitMapInfoHeader);
HDC pDC = CreateCompatibleDC(NULL); // get a device context for the screen.
result = GetDIBits(pDC, pIconInfo.hbmColor, 0, 0, NULL, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0 && pBitMapInfo.bmiHeader.biSizeImage > 0)
{
// allocate a buffer to hold the bit map....this should be a buffer that's biSizeImage...
unsigned char * buffer = (PRUint8 *) nsMemory::Alloc(pBitMapInfo.bmiHeader.biSizeImage);
result = GetDIBits(pDC, pIconInfo.hbmColor, 0, pBitMapInfo.bmiHeader.biHeight, (void *) buffer, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0)
{
PRUint32 bytesPerPixel = pBitMapInfo.bmiHeader.biBitCount / 8;
InvertRows(buffer, pBitMapInfo.bmiHeader.biSizeImage, pBitMapInfo.bmiHeader.biWidth * bytesPerPixel);
// Convert our little icon buffer which is padded to 4 bytes per pixel into a nice 3 byte per pixel
// description.
nsCString iconBuffer;
iconBuffer.Assign((char) pBitMapInfo.bmiHeader.biWidth);
iconBuffer.Append((char) pBitMapInfo.bmiHeader.biHeight);
PRInt32 index = 0;
if (pBitMapInfo.bmiHeader.biBitCount == 16)
{
PRUint8 redValue, greenValue, blueValue, partialGreen;
while (index < pBitMapInfo.bmiHeader.biSizeImage)
{
DWORD dst=(DWORD) buffer[index];
PRUint16 num = 0;
num = (PRUint8) buffer[index];
num <<= 8;
num |= (PRUint8) buffer[index+1];
//blueValue = (PRUint8)((*dst)&(0x1F));
//greenValue = (PRUint8)(((*dst)>>5)&(0x1F));
//redValue = (PRUint8)(((*dst)>>10)&(0x1F));
redValue = ((PRUint32) (((float)(num & 0x7c00) / 0x7c00) * 0xFF0000) & 0xFF0000)>> 16;
greenValue = ((PRUint32)(((float)(num & 0x03E0) / 0x03E0) * 0x00FF00) & 0x00FF00)>> 8;
blueValue = ((PRUint32)(((float)(num & 0x001F) / 0x001F) * 0x0000FF) & 0x0000FF);
// now we have the right RGB values...
iconBuffer.Append((char) redValue);
iconBuffer.Append((char) greenValue);
iconBuffer.Append((char) blueValue);
index += bytesPerPixel;
}
}
else
{
while (index <pBitMapInfo.bmiHeader.biSizeImage)
{
iconBuffer.Append((char) buffer[index]);
iconBuffer.Append((char) buffer[index+1]);
iconBuffer.Append((char) buffer[index+2]);
index += bytesPerPixel;
}
}
// now we need to tack on the alpha data...which is hbmMask
pBitMapInfo.bmiHeader.biBitCount = 0;
pBitMapInfo.bmiHeader.biSize = sizeof(pBitMapInfoHeader);
result = GetDIBits(pDC, pIconInfo.hbmMask, 0, 0, NULL, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0 && pBitMapInfo.bmiHeader.biSizeImage > 0)
{
// allocate a buffer to hold the bit map....this should be a buffer that's biSizeImage...
unsigned char * maskBuffer = (PRUint8 *) nsMemory::Alloc(pBitMapInfo.bmiHeader.biSizeImage);
result = GetDIBits(pDC, pIconInfo.hbmMask, 0, pBitMapInfo.bmiHeader.biHeight, (void *) maskBuffer, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0)
{
InvertRows(maskBuffer, pBitMapInfo.bmiHeader.biSizeImage, 4);
index = 0;
// for some reason the bit mask on windows are flipped from the values we really want for transparency.
// So complement each byte in the bit mask.
while (index < pBitMapInfo.bmiHeader.biSizeImage)
{
maskBuffer[index]^=255;
index += 1;
}
iconBuffer.Append((char *) maskBuffer, pBitMapInfo.bmiHeader.biSizeImage);
}
nsMemory::Free(maskBuffer);
} // if we have a mask buffer to apply
// turn our nsString into a stream looking object...
aListener->OnStartRequest(this, ctxt);
// turn our string into a stream...
nsCOMPtr<nsISupports> streamSupports;
NS_NewByteInputStream(getter_AddRefs(streamSupports), iconBuffer.get(), iconBuffer.Length());
nsCOMPtr<nsIInputStream> inputStr (do_QueryInterface(streamSupports));
aListener->OnDataAvailable(this, ctxt, inputStr, 0, iconBuffer.Length());
aListener->OnStopRequest(this, ctxt, NS_OK, nsnull);
} // if we got valid bits for the main bitmap mask
nsMemory::Free(buffer);
}
DeleteDC(pDC);
}
}
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetLoadAttributes(PRUint32 *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadAttributes(PRUint32 aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetContentType(char* *aContentType)
{
if (!aContentType) return NS_ERROR_NULL_POINTER;
*aContentType = nsCRT::strdup("image/icon");
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::SetContentType(const char *aContentType)
{
//It doesn't make sense to set the content-type on this type
// of channel...
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt32 aContentLength)
{
NS_NOTREACHED("nsIconChannel::SetContentLength");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
*aNotificationCallbacks = mCallbacks.get();
NS_IF_ADDREF(*aNotificationCallbacks);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
*aSecurityInfo = nsnull;
return NS_OK;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconChannel_h___
#define nsIconChannel_h___
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIURI.h"
class nsIconChannel : public nsIChannel
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
nsIconChannel();
virtual ~nsIconChannel();
nsresult Init(nsIURI* uri);
protected:
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
PRUint32 mLoadAttributes;
PRInt32 mContentLength;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsISupports> mOwner;
nsresult mStatus;
};
#endif /* nsIconChannel_h___ */

View File

@@ -0,0 +1,42 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imgjpeg
LIBRARY_NAME = imgjpeg
IS_COMPONENT = 1
REQUIRES = xpcom string necko layout jpeg gfx2 imglib2
CPPSRCS = nsJPEGDecoder.cpp nsJPEGFactory.cpp
EXTRA_DSO_LDOPTS = $(JPEG_LIBS) $(ZLIB_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,52 @@
#!nmake
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imgjpeg
LIBRARY_NAME = imgjpeg
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsJPEGDecoder.obj \
.\$(OBJDIR)\nsJPEGFactory.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\jpeg3250.lib \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,829 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
*/
#include "nsJPEGDecoder.h"
#include "nsIInputStream.h"
#include "nspr.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "imgIContainerObserver.h"
#include "ImageLogging.h"
NS_IMPL_ISUPPORTS2(nsJPEGDecoder, imgIDecoder, nsIOutputStream)
#if defined(PR_LOGGING)
PRLogModuleInfo *gJPEGlog = PR_NewLogModule("JPEGDecoder");
#else
#define gJPEGlog
#endif
void PR_CALLBACK init_source (j_decompress_ptr jd);
boolean PR_CALLBACK fill_input_buffer (j_decompress_ptr jd);
void PR_CALLBACK skip_input_data (j_decompress_ptr jd, long num_bytes);
void PR_CALLBACK term_source (j_decompress_ptr jd);
void PR_CALLBACK my_error_exit (j_common_ptr cinfo);
/* Normal JFIF markers can't have more bytes than this. */
#define MAX_JPEG_MARKER_LENGTH (((PRUint32)1 << 16) - 1)
/* Possible states for JPEG source manager */
enum data_source_state {
READING_BACK = 0, /* Must be zero for init purposes */
READING_NEW
};
/*
* Implementation of a JPEG src object that understands our state machine
*/
typedef struct {
/* public fields; must be first in this struct! */
struct jpeg_source_mgr pub;
nsJPEGDecoder *decoder;
} decoder_source_mgr;
nsJPEGDecoder::nsJPEGDecoder()
{
NS_INIT_ISUPPORTS();
mState = JPEG_HEADER;
mFillState = READING_BACK;
mSamples = nsnull;
mSamples3 = nsnull;
mRGBPadRow = nsnull;
mRGBPadRowLength = 0;
mBytesToSkip = 0;
memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
mCompletedPasses = 0;
mBuffer = nsnull;
mBufferLen = mBufferSize = 0;
mBackBuffer = nsnull;
mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0;
}
nsJPEGDecoder::~nsJPEGDecoder()
{
if (mBuffer)
PR_Free(mBuffer);
if (mBackBuffer)
PR_Free(mBackBuffer);
if (mRGBPadRow)
PR_Free(mRGBPadRow);
}
/** imgIDecoder methods **/
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsJPEGDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(mRequest);
aRequest->GetImage(getter_AddRefs(mImage));
/* We set up the normal JPEG error routines, then override error_exit. */
mInfo.err = jpeg_std_error(&mErr.pub);
/* mInfo.err = jpeg_std_error(&mErr.pub); */
mErr.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(mErr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
return NS_ERROR_FAILURE;
}
/* Step 1: allocate and initialize JPEG decompression object */
jpeg_create_decompress(&mInfo);
decoder_source_mgr *src;
if (mInfo.src == NULL) {
//mInfo.src = PR_NEWZAP(decoder_source_mgr);
src = PR_NEWZAP(decoder_source_mgr);
if (!src) {
return PR_FALSE;
}
mInfo.src = (struct jpeg_source_mgr *) src;
}
/* Step 2: specify data source (eg, a file) */
/* Setup callback functions. */
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = term_source;
src->decoder = this;
return NS_OK;
}
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsJPEGDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
/* void close (); */
NS_IMETHODIMP nsJPEGDecoder::Close()
{
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::Close\n", this));
if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER)
NS_WARNING("Never finished decoding the JPEG.");
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress(&mInfo);
return NS_OK;
}
/* void flush (); */
NS_IMETHODIMP nsJPEGDecoder::Flush()
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::Flush");
PRUint32 ret;
if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER)
return this->WriteFrom(nsnull, 0, &ret);
return NS_OK;
}
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsJPEGDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
LOG_SCOPE_WITH_PARAM(gJPEGlog, "nsJPEGDecoder::WriteFrom", "count", count);
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
// XXX above what is this?
if (inStr) {
if (!mBuffer) {
mBuffer = (JOCTET *)PR_Malloc(count);
mBufferSize = count;
} else if (count > mBufferSize) {
mBuffer = (JOCTET *)PR_Realloc(mBuffer, count);
mBufferSize = count;
}
nsresult rv = inStr->Read((char*)mBuffer, count, &mBufferLen);
*_retval = mBufferLen;
//nsresult rv = mOutStream->WriteFrom(inStr, count, _retval);
NS_ASSERTION(NS_SUCCEEDED(rv), "nsJPEGDecoder::WriteFrom -- mOutStream->WriteFrom failed");
}
// else no input stream.. Flush() ?
nsresult error_code = NS_ERROR_FAILURE;
/* Return here if there is a fatal error. */
if ((error_code = setjmp(mErr.setjmp_buffer)) != 0) {
return error_code;
}
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::WriteFrom -- processing JPEG data\n", this));
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, mInfo.src);
switch (mState) {
case JPEG_HEADER:
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_HEADER case");
/* Step 3: read file parameters with jpeg_read_header() */
if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED)
return NS_OK; /* I/O suspension */
/*
* Don't allocate a giant and superfluous memory buffer
* when the image is a sequential JPEG.
*/
mInfo.buffered_image = jpeg_has_multiple_scans(&mInfo);
/* Used to set up image size so arrays can be allocated */
jpeg_calc_output_dimensions(&mInfo);
mObserver->OnStartDecode(nsnull, nsnull);
mImage->Init(mInfo.image_width, mInfo.image_height, mObserver);
mObserver->OnStartContainer(nsnull, nsnull, mImage);
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
gfx_format format;
#ifdef XP_PC
format = gfxIFormats::BGR;
#else
format = gfxIFormats::RGB;
#endif
mFrame->Init(0, 0, mInfo.image_width, mInfo.image_height, format);
mImage->AppendFrame(mFrame);
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
/*
* Make a one-row-high sample array that will go away
* when done with image. Always make it big enough to
* hold an RGB row. Since this uses the IJG memory
* manager, it must be allocated before the call to
* jpeg_start_compress().
*/
int row_stride;
if(mInfo.output_components == 1)
row_stride = mInfo.output_width;
else
row_stride = mInfo.output_width * 4; // use 4 instead of mInfo.output_components
// so we don't have to fuss with byte alignment.
// Mac wants 4 anyways.
mSamples = (*mInfo.mem->alloc_sarray)((j_common_ptr) &mInfo,
JPOOL_IMAGE,
row_stride, 1);
#if defined(XP_PC) || defined(XP_MAC)
// allocate buffer to do byte flipping if needed
if (mInfo.output_components == 3) {
mRGBPadRow = (PRUint8*) PR_MALLOC(row_stride);
mRGBPadRowLength = row_stride;
memset(mRGBPadRow, 0, mRGBPadRowLength);
}
#endif
/* Allocate RGB buffer for conversion from greyscale. */
if (mInfo.output_components != 3) {
row_stride = mInfo.output_width * 4;
mSamples3 = (*mInfo.mem->alloc_sarray)((j_common_ptr) &mInfo,
JPOOL_IMAGE,
row_stride, 1);
}
mState = JPEG_START_DECOMPRESS;
}
case JPEG_START_DECOMPRESS:
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_START_DECOMPRESS case");
/* Step 4: set parameters for decompression */
/* FIXME -- Should reset dct_method and dither mode
* for final pass of progressive JPEG
*/
mInfo.dct_method = JDCT_FASTEST;
mInfo.dither_mode = JDITHER_ORDERED;
mInfo.do_fancy_upsampling = FALSE;
mInfo.enable_2pass_quant = FALSE;
mInfo.do_block_smoothing = TRUE;
/* Step 5: Start decompressor */
if (jpeg_start_decompress(&mInfo) == FALSE)
return NS_OK; /* I/O suspension */
/* If this is a progressive JPEG ... */
if (mInfo.buffered_image) {
mState = JPEG_DECOMPRESS_PROGRESSIVE;
} else {
mState = JPEG_DECOMPRESS_SEQUENTIAL;
}
}
case JPEG_DECOMPRESS_SEQUENTIAL:
{
if (mState == JPEG_DECOMPRESS_SEQUENTIAL)
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- JPEG_DECOMPRESS_SEQUENTIAL case");
if (OutputScanlines(-1) == PR_FALSE)
return NS_OK; /* I/O suspension */
/* If we've completed image output ... */
NS_ASSERTION(mInfo.output_scanline == mInfo.output_height, "We didn't process all of the data!");
mState = JPEG_DONE;
}
}
case JPEG_DECOMPRESS_PROGRESSIVE:
{
if (mState == JPEG_DECOMPRESS_PROGRESSIVE)
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- JPEG_DECOMPRESS_PROGRESSIVE case");
int status;
do {
status = jpeg_consume_input(&mInfo);
} while (!((status == JPEG_SUSPENDED) ||
(status == JPEG_REACHED_EOI)));
switch (status) {
case JPEG_REACHED_EOI:
// End of image
mState = JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT;
break;
case JPEG_SUSPENDED:
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::WriteFrom -- suspending\n", this));
return NS_OK; /* I/O suspension */
default:
printf("got someo other state!?\n");
}
}
}
case JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT:
{
if (mState == JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT)
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT case");
// XXX progressive? ;)
// not really progressive according to the state machine... -saari
jpeg_start_output(&mInfo, mInfo.input_scan_number);
if (OutputScanlines(-1) == PR_FALSE)
return NS_OK; /* I/O suspension */
jpeg_finish_output(&mInfo);
mState = JPEG_DONE;
}
}
case JPEG_DONE:
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_DONE case");
/* Step 7: Finish decompression */
if (jpeg_finish_decompress(&mInfo) == FALSE)
return NS_OK; /* I/O suspension */
mState = JPEG_SINK_NON_JPEG_TRAILER;
/* we're done dude */
break;
}
case JPEG_SINK_NON_JPEG_TRAILER:
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::WriteFrom -- entering JPEG_SINK_NON_JPEG_TRAILER case\n", this));
break;
}
return NS_OK;
}
int
nsJPEGDecoder::OutputScanlines(int num_scanlines)
{
int pass = 0;
if (mState == JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT)
pass = -1;
else
pass = mCompletedPasses + 1;
while ((mInfo.output_scanline < mInfo.output_height) && num_scanlines--) {
JSAMPROW samples;
/* Request one scanline. Returns 0 or 1 scanlines. */
int ns = jpeg_read_scanlines(&mInfo, mSamples, 1);
if (ns != 1) {
return PR_FALSE; /* suspend */
}
/* If grayscale image ... */
if (mInfo.output_components == 1) {
JSAMPLE j;
JSAMPLE *j1 = mSamples[0];
const JSAMPLE *j1end = j1 + mInfo.output_width;
JSAMPLE *j3 = mSamples3[0];
/* Convert from grayscale to RGB. */
while (j1 < j1end) {
#ifdef XP_MAC
j = *j1++;
j3[0] = 0;
j3[1] = j;
j3[2] = j;
j3[3] = j;
j3 += 4;
#else
j = *j1++;
j3[0] = j;
j3[1] = j;
j3[2] = j;
j3 += 3;
#endif
}
samples = mSamples3[0];
} else {
/* 24-bit color image */
#ifdef XP_PC
memset(mRGBPadRow, 0, mInfo.output_width * 4);
PRUint8 *ptrOutputBuf = mRGBPadRow;
JSAMPLE *j1 = mSamples[0];
for (PRUint32 i=0;i<mInfo.output_width;++i) {
ptrOutputBuf[2] = *j1++;
ptrOutputBuf[1] = *j1++;
ptrOutputBuf[0] = *j1++;
ptrOutputBuf += 3;
}
samples = mRGBPadRow;
#else
#ifdef XP_MAC
memset(mRGBPadRow, 0, mInfo.output_width * 4);
PRUint8 *ptrOutputBuf = mRGBPadRow;
JSAMPLE *j1 = mSamples[0];
for (PRUint32 i=0;i<mInfo.output_width;++i) {
ptrOutputBuf[0] = 0;
ptrOutputBuf[1] = *j1++;
ptrOutputBuf[2] = *j1++;
ptrOutputBuf[3] = *j1++;
ptrOutputBuf += 4;
}
samples = mRGBPadRow;
#else
samples = mSamples[0];
#endif
#endif
}
PRUint32 bpr;
mFrame->GetImageBytesPerRow(&bpr);
mFrame->SetImageData(
samples, // data
bpr, // length
(mInfo.output_scanline-1) * bpr); // offset
nsRect r(0, mInfo.output_scanline, mInfo.output_width, 1);
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
}
return PR_TRUE;
}
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsJPEGDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsJPEGDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsJPEGDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsJPEGDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsJPEGDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* Override the standard error method in the IJG JPEG decoder code. */
void PR_CALLBACK
my_error_exit (j_common_ptr cinfo)
{
nsresult error_code = NS_ERROR_FAILURE;
decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err;
#if 0
#ifdef DEBUG
/*ptn fix later */
if (il_debug >= 1) {
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
ILTRACE(1,("%s\n", buffer));
}
#endif
/* Convert error to a browser error code */
if (cinfo->err->msg_code == JERR_OUT_OF_MEMORY)
error_code = MK_OUT_OF_MEMORY;
else
error_code = MK_IMAGE_LOSSAGE;
#endif
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
fprintf(stderr, "my_error_exit()\n%s\n", buffer);
/* Return control to the setjmp point. */
longjmp(err->setjmp_buffer, error_code);
}
/******************************************************************************/
/*-----------------------------------------------------------------------------
* This is the callback routine from the IJG JPEG library used to supply new
* data to the decompressor when its input buffer is exhausted. It juggles
* multiple buffers in an attempt to avoid unnecessary copying of input data.
*
* (A simpler scheme is possible: It's much easier to use only a single
* buffer; when fill_input_buffer() is called, move any unconsumed data
* (beyond the current pointer/count) down to the beginning of this buffer and
* then load new data into the remaining buffer space. This approach requires
* a little more data copying but is far easier to get right.)
*
* At any one time, the JPEG decompressor is either reading from the necko
* input buffer, which is volatile across top-level calls to the IJG library,
* or the "backtrack" buffer. The backtrack buffer contains the remaining
* unconsumed data from the necko buffer after parsing was suspended due
* to insufficient data in some previous call to the IJG library.
*
* When suspending, the decompressor will back up to a convenient restart
* point (typically the start of the current MCU). The variables
* next_input_byte & bytes_in_buffer indicate where the restart point will be
* if the current call returns FALSE. Data beyond this point must be
* rescanned after resumption, so it must be preserved in case the decompressor
* decides to backtrack.
*
* Returns:
* TRUE if additional data is available, FALSE if no data present and
* the JPEG library should therefore suspend processing of input stream
*---------------------------------------------------------------------------*/
/******************************************************************************/
/* data source manager method
/******************************************************************************/
/******************************************************************************/
/* data source manager method
Initialize source. This is called by jpeg_read_header() before any
data is actually read. May leave
bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
will occur immediately).
*/
void PR_CALLBACK
init_source (j_decompress_ptr jd)
{
}
/******************************************************************************/
/* data source manager method
Skip num_bytes worth of data. The buffer pointer and count should
be advanced over num_bytes input bytes, refilling the buffer as
needed. This is used to skip over a potentially large amount of
uninteresting data (such as an APPn marker). In some applications
it may be possible to optimize away the reading of the skipped data,
but it's not clear that being smart is worth much trouble; large
skips are uncommon. bytes_in_buffer may be zero on return.
A zero or negative skip count should be treated as a no-op.
*/
void PR_CALLBACK
skip_input_data (j_decompress_ptr jd, long num_bytes)
{
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
if (num_bytes > (long)src->pub.bytes_in_buffer) {
/*
* Can't skip it all right now until we get more data from
* network stream. Set things up so that fill_input_buffer
* will skip remaining amount.
*/
src->decoder->mBytesToSkip = (size_t)num_bytes - src->pub.bytes_in_buffer;
src->pub.next_input_byte += src->pub.bytes_in_buffer;
src->pub.bytes_in_buffer = 0;
} else {
/* Simple case. Just advance buffer pointer */
src->pub.bytes_in_buffer -= (size_t)num_bytes;
src->pub.next_input_byte += num_bytes;
}
}
/******************************************************************************/
/* data source manager method
This is called whenever bytes_in_buffer has reached zero and more
data is wanted. In typical applications, it should read fresh data
into the buffer (ignoring the current state of next_input_byte and
bytes_in_buffer), reset the pointer & count to the start of the
buffer, and return TRUE indicating that the buffer has been reloaded.
It is not necessary to fill the buffer entirely, only to obtain at
least one more byte. bytes_in_buffer MUST be set to a positive value
if TRUE is returned. A FALSE return should only be used when I/O
suspension is desired.
*/
boolean PR_CALLBACK
fill_input_buffer (j_decompress_ptr jd)
{
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
unsigned char *new_buffer = (unsigned char *)src->decoder->mBuffer;
PRUint32 new_buflen = src->decoder->mBufferLen;
PRUint32 bytesToSkip = src->decoder->mBytesToSkip;
switch(src->decoder->mFillState) {
case READING_BACK:
{
if (!new_buffer || new_buflen == 0)
return PR_FALSE; /* suspend */
src->decoder->mBufferLen = 0;
if (bytesToSkip != 0) {
if (bytesToSkip < new_buflen) {
/* All done skipping bytes; Return what's left. */
new_buffer += bytesToSkip;
new_buflen -= bytesToSkip;
src->decoder->mBytesToSkip = 0;
} else {
/* Still need to skip some more data in the future */
src->decoder->mBytesToSkip -= (size_t)new_buflen;
return PR_FALSE; /* suspend */
}
}
src->decoder->mBackBufferUnreadLen = src->pub.bytes_in_buffer;
src->pub.next_input_byte = new_buffer;
src->pub.bytes_in_buffer = (size_t)new_buflen;
src->decoder->mFillState = READING_NEW;
return PR_TRUE;
}
break;
case READING_NEW:
{
if (src->pub.next_input_byte != src->decoder->mBuffer) {
/* Backtrack data has been permanently consumed. */
src->decoder->mBackBufferUnreadLen = 0;
src->decoder->mBackBufferLen = 0;
}
/* Save remainder of netlib buffer in backtrack buffer */
PRUint32 new_backtrack_buflen = src->pub.bytes_in_buffer + src->decoder->mBackBufferLen;
/* Make sure backtrack buffer is big enough to hold new data. */
if (src->decoder->mBackBufferSize < new_backtrack_buflen) {
/* Round up to multiple of 16 bytes. */
PRUint32 roundup_buflen = ((new_backtrack_buflen + 15) >> 4) << 4;
if (src->decoder->mBackBufferSize) {
src->decoder->mBackBuffer =
(JOCTET *)PR_REALLOC(src->decoder->mBackBuffer, roundup_buflen);
} else {
src->decoder->mBackBuffer = (JOCTET*)PR_MALLOC(roundup_buflen);
}
/* Check for OOM */
if (!src->decoder->mBackBuffer) {
#if 0
j_common_ptr cinfo = (j_common_ptr)(&src->js->jd);
cinfo->err->msg_code = JERR_OUT_OF_MEMORY;
my_error_exit(cinfo);
#endif
}
src->decoder->mBackBufferSize = (size_t)roundup_buflen;
/* Check for malformed MARKER segment lengths. */
if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) {
my_error_exit((j_common_ptr)(&src->decoder->mInfo));
}
}
/* Copy remainder of netlib buffer into backtrack buffer. */
nsCRT::memmove(src->decoder->mBackBuffer + src->decoder->mBackBufferLen,
src->pub.next_input_byte,
src->pub.bytes_in_buffer);
/* Point to start of data to be rescanned. */
src->pub.next_input_byte = src->decoder->mBackBuffer + src->decoder->mBackBufferLen - src->decoder->mBackBufferUnreadLen;
src->pub.bytes_in_buffer += src->decoder->mBackBufferUnreadLen;
src->decoder->mBackBufferLen = (size_t)new_backtrack_buflen;
src->decoder->mFillState = READING_BACK;
return PR_FALSE;
}
break;
}
return PR_FALSE;
}
/******************************************************************************/
/* data source manager method */
/*
* Terminate source --- called by jpeg_finish_decompress() after all
* data has been read to clean up JPEG source manager. NOT called by
* jpeg_abort() or jpeg_destroy().
*/
void PR_CALLBACK
term_source (j_decompress_ptr jd)
{
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
if (src->decoder->mObserver) {
src->decoder->mObserver->OnStopFrame(nsnull, nsnull, src->decoder->mFrame);
src->decoder->mObserver->OnStopContainer(nsnull, nsnull, src->decoder->mImage);
src->decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
/* No work necessary here */
}

View File

@@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsJPEGDecoder_h__
#define nsJPEGDecoder_h__
#include "imgIDecoder.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "imgIDecoderObserver.h"
#include "imgIRequest.h"
#include "nsIInputStream.h"
#include "nsIPipe.h"
extern "C" {
#include "jpeglib.h"
}
#include <setjmp.h>
#define NS_JPEGDECODER_CID \
{ /* 5871a422-1dd2-11b2-ab3f-e2e56be5da9c */ \
0x5871a422, \
0x1dd2, \
0x11b2, \
{0xab, 0x3f, 0xe2, 0xe5, 0x6b, 0xe5, 0xda, 0x9c} \
}
typedef struct {
struct jpeg_error_mgr pub; /* "public" fields for IJG library*/
jmp_buf setjmp_buffer; /* For handling catastropic errors */
} decoder_error_mgr;
typedef enum {
JPEG_HEADER, /* Reading JFIF headers */
JPEG_START_DECOMPRESS,
JPEG_DECOMPRESS_PROGRESSIVE, /* Output progressive pixels */
JPEG_DECOMPRESS_SEQUENTIAL, /* Output sequential pixels */
JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT,
JPEG_DONE,
JPEG_SINK_NON_JPEG_TRAILER, /* Some image files have a */
/* non-JPEG trailer */
JPEG_ERROR
} jstate;
class nsJPEGDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsJPEGDecoder();
virtual ~nsJPEGDecoder();
PRBool FillInput(j_decompress_ptr jd);
PRUint32 mBytesToSkip;
protected:
int OutputScanlines(int num_scanlines);
public:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver;
struct jpeg_decompress_struct mInfo;
decoder_error_mgr mErr;
jstate mState;
JSAMPARRAY mSamples;
JSAMPARRAY mSamples3;
PRUint8* mRGBPadRow;
PRUint32 mRGBPadRowLength;
PRInt32 mCompletedPasses;
PRInt32 mPasses;
int mFillState;
JOCTET *mBuffer;
PRUint32 mBufferLen; // amount of data currently in mBuffer
PRUint32 mBufferSize; // size in bytes what mBuffer was created with
JOCTET *mBackBuffer;
PRUint32 mBackBufferLen; // Offset of end of active backtrack data
PRUint32 mBackBufferSize; // size in bytes what mBackBuffer was created with
PRUint32 mBackBufferUnreadLen; // amount of data currently in mBackBuffer
};
#endif // nsJPEGDecoder_h__

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsJPEGDecoder.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGDecoder)
static nsModuleComponentInfo components[] =
{
{ "ppm decoder",
NS_JPEGDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/jpeg",
nsJPEGDecoderConstructor, },
};
NS_IMPL_NSGETMODULE("nsJPEGDecoderModule", components)

View File

@@ -0,0 +1,16 @@
?Release@nsJPEGDecoder@@UAGKXZ ; 172
?AddRef@nsJPEGDecoder@@UAGKXZ ; 172
?fill_input_buffer@@YAEPAUjpeg_decompress_struct@@@Z ; 126
?skip_input_data@@YAXPAUjpeg_decompress_struct@@J@Z ; 109
?WriteFrom@nsJPEGDecoder@@UAGIPAVnsIInputStream@@IPAI@Z ; 106
?OutputScanlines@nsJPEGDecoder@@IAEHH@Z ; 93
?init_source@@YAXPAUjpeg_decompress_struct@@@Z ; 86
??1nsJPEGDecoder@@UAE@XZ ; 86
?Close@nsJPEGDecoder@@UAGIXZ ; 86
?term_source@@YAXPAUjpeg_decompress_struct@@@Z ; 86
?Init@nsJPEGDecoder@@UAGIPAVimgIRequest@@@Z ; 86
??0nsJPEGDecoder@@QAE@XZ ; 86
?Flush@nsJPEGDecoder@@UAGIXZ ; 86
?QueryInterface@nsJPEGDecoder@@UAGIABUnsID@@PAPAX@Z ; 86
??_EnsJPEGDecoder@@UAEPAXI@Z ; 86
_NSGetModule ; 1

View File

@@ -0,0 +1,26 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH=..\..\..
DIRS = ppm gif png jpeg
!include $(DEPTH)\config\rules.mak

View File

@@ -0,0 +1,42 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imgpng
LIBRARY_NAME = imgpng
IS_COMPONENT = 1
REQUIRES = xpcom necko layout png gfx2 imglib2
CPPSRCS = nsPNGDecoder.cpp nsPNGFactory.cpp
EXTRA_DSO_LDOPTS = $(PNG_LIBS) $(ZLIB_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,53 @@
#!nmake
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imgpng
LIBRARY_NAME = imgpng
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsPNGDecoder.obj \
.\$(OBJDIR)\nsPNGFactory.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\png.lib \
$(DIST)\lib\zlib.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,553 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
*/
#include "nsPNGDecoder.h"
#include "nsIInputStream.h"
#include "nspr.h"
#include "nsIComponentManager.h"
#include "png.h"
#include "nsIStreamObserver.h"
#include "nsRect.h"
#include "nsMemory.h"
#include "imgIContainerObserver.h"
// XXX we need to be sure to fire onStopDecode messages to mObserver in error cases.
NS_IMPL_ISUPPORTS2(nsPNGDecoder, imgIDecoder, nsIOutputStream)
nsPNGDecoder::nsPNGDecoder()
{
NS_INIT_ISUPPORTS();
mPNG = nsnull;
mInfo = nsnull;
colorLine = 0;
alphaLine = 0;
interlacebuf = 0;
}
nsPNGDecoder::~nsPNGDecoder()
{
if (colorLine)
nsMemory::Free(colorLine);
if (alphaLine)
nsMemory::Free(alphaLine);
if (interlacebuf)
nsMemory::Free(interlacebuf);
}
/** imgIDecoder methods **/
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsPNGDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImage));
/* do png init stuff */
/* Initialize the container's source image header. */
/* Always decode to 24 bit pixdepth */
mPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL,
NULL);
if (!mPNG) {
return NS_ERROR_FAILURE;
}
mInfo = png_create_info_struct(mPNG);
if (!mInfo) {
png_destroy_read_struct(&mPNG, NULL, NULL);
return NS_ERROR_FAILURE;
}
/* use ic as libpng "progressive pointer" (retrieve in callbacks) */
png_set_progressive_read_fn(mPNG, NS_STATIC_CAST(png_voidp, this), nsPNGDecoder::info_callback, nsPNGDecoder::row_callback, nsPNGDecoder::end_callback);
return NS_OK;
}
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsPNGDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
/* void close (); */
NS_IMETHODIMP nsPNGDecoder::Close()
{
if (mPNG)
png_destroy_read_struct(&mPNG, mInfo ? &mInfo : NULL, NULL);
return NS_OK;
}
/* void flush (); */
NS_IMETHODIMP nsPNGDecoder::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsPNGDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static NS_METHOD ReadDataOut(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount)
{
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, closure);
// we need to do the setjmp here otherwise bad things will happen
if (setjmp(decoder->mPNG->jmpbuf)) {
png_destroy_read_struct(&decoder->mPNG, &decoder->mInfo, NULL);
// is this NS_ERROR_FAILURE enough?
decoder->mRequest->Cancel(NS_BINDING_ABORTED); // XXX is this the correct error ?
return NS_ERROR_FAILURE;
}
*writeCount = decoder->ProcessData((unsigned char*)fromRawSegment, count);
return NS_OK;
}
PRUint32 nsPNGDecoder::ProcessData(unsigned char *data, PRUint32 count)
{
png_process_data(mPNG, mInfo, data, count);
return count; // we always consume all the data
}
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsPNGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
// PRUint32 sourceOffset = *_retval;
inStr->ReadSegments(ReadDataOut, this, count, _retval);
return NS_OK;
}
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsPNGDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsPNGDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPNGDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsPNGDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPNGDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
void
nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
{
/* int number_passes; NOT USED */
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, compression_type, filter_type;
int channels;
double LUT_exponent, CRT_exponent = 2.2, display_exponent, aGamma;
png_bytep trans=NULL;
int num_trans =0;
/* always decode to 24-bit RGB or 32-bit RGBA */
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, &compression_type, &filter_type);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
png_set_expand(png_ptr);
}
if (bit_depth == 16)
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
#ifdef XP_PC
// windows likes BGR
png_set_bgr(png_ptr);
#endif
/* set up gamma correction for Mac, Unix and (Win32 and everything else)
* using educated guesses for display-system exponents; do preferences
* later */
#if defined(XP_MAC)
LUT_exponent = 1.8 / 2.61;
#elif defined(XP_UNIX)
# if defined(__sgi)
LUT_exponent = 1.0 / 1.7; /* typical default for SGI console */
# elif defined(NeXT)
LUT_exponent = 1.0 / 2.2; /* typical default for NeXT cube */
# else
LUT_exponent = 1.0; /* default for most other Unix workstations */
# endif
#else
LUT_exponent = 1.0; /* virtually all PCs and most other systems */
#endif
/* (alternatively, could check for SCREEN_GAMMA environment variable) */
display_exponent = LUT_exponent * CRT_exponent;
if (png_get_gAMA(png_ptr, info_ptr, &aGamma))
png_set_gamma(png_ptr, display_exponent, aGamma);
else
png_set_gamma(png_ptr, display_exponent, 0.45455);
/* let libpng expand interlaced images */
if (interlace_type == PNG_INTERLACE_ADAM7) {
/* number_passes = */
png_set_interlace_handling(png_ptr);
}
/* now all of those things we set above are used to update various struct
* members and whatnot, after which we can get channels, rowbytes, etc. */
png_read_update_info(png_ptr, info_ptr);
channels = png_get_channels(png_ptr, info_ptr);
PR_ASSERT(channels == 3 || channels == 4);
/*---------------------------------------------------------------*/
/* copy PNG info into imagelib structs (formerly png_set_dims()) */
/*---------------------------------------------------------------*/
PRInt32 alpha_bits = 1;
if (channels > 3) {
/* check if alpha is coming from a tRNS chunk and is binary */
if (num_trans) {
/* if it's not a indexed color image, tRNS means binary */
if (color_type == PNG_COLOR_TYPE_PALETTE) {
for (int i=0; i<num_trans; i++) {
if ((trans[i] != 0) && (trans[i] != 255)) {
alpha_bits = 8;
break;
}
}
}
} else {
alpha_bits = 8;
}
}
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
if (decoder->mObserver)
decoder->mObserver->OnStartDecode(nsnull, nsnull);
// since the png is only 1 frame, initalize the container to the width and height of the frame
decoder->mImage->Init(width, height, decoder->mObserver);
if (decoder->mObserver)
decoder->mObserver->OnStartContainer(nsnull, nsnull, decoder->mImage);
decoder->mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
#if 0
// XXX should we longjmp to png_ptr->jumpbuf here if we failed?
if (!decoder->mFrame)
return NS_ERROR_FAILURE;
#endif
gfx_format format;
if (channels == 3) {
format = gfxIFormats::RGB;
} else if (channels > 3) {
if (alpha_bits == 8) {
decoder->mImage->GetPreferredAlphaChannelFormat(&format);
} else if (alpha_bits == 1) {
format = gfxIFormats::RGB_A1;
}
}
#ifdef XP_PC
// XXX this works...
format += 1; // RGB to BGR
#endif
// then initalize the frame and append it to the container
decoder->mFrame->Init(0, 0, width, height, format);
decoder->mImage->AppendFrame(decoder->mFrame);
if (decoder->mObserver)
decoder->mObserver->OnStartFrame(nsnull, nsnull, decoder->mFrame);
PRUint32 bpr, abpr;
decoder->mFrame->GetImageBytesPerRow(&bpr);
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
decoder->colorLine = (PRUint8 *)nsMemory::Alloc(bpr);
if (channels > 3)
decoder->alphaLine = (PRUint8 *)nsMemory::Alloc(abpr);
if (interlace_type == PNG_INTERLACE_ADAM7) {
decoder->interlacebuf = (PRUint8 *)nsMemory::Alloc(channels*width*height);
decoder->ibpr = channels*width;
if (!decoder->interlacebuf) {
// return NS_ERROR_FAILURE;
}
}
return;
}
void
nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass)
{
/* libpng comments:
*
* this function is called for every row in the image. If the
* image is interlacing, and you turned on the interlace handler,
* this function will be called for every row in every pass.
* Some of these rows will not be changed from the previous pass.
* When the row is not changed, the new_row variable will be NULL.
* The rows and passes are called in order, so you don't really
* need the row_num and pass, but I'm supplying them because it
* may make your life easier.
*
* For the non-NULL rows of interlaced images, you must call
* png_progressive_combine_row() passing in the row and the
* old row. You can call this function for NULL rows (it will
* just return) and for non-interlaced images (it just does the
* memcpy for you) if it will make the code easier. Thus, you
* can just do this for all cases:
*
* png_progressive_combine_row(png_ptr, old_row, new_row);
*
* where old_row is what was displayed for previous rows. Note
* that the first pass (pass == 0 really) will completely cover
* the old row, so the rows do not have to be initialized. After
* the first pass (and only for interlaced images), you will have
* to pass the current row, and the function will combine the
* old row and the new row.
*/
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
PRUint32 bpr, abpr;
decoder->mFrame->GetImageBytesPerRow(&bpr);
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
png_bytep line;
if (decoder->interlacebuf) {
line = decoder->interlacebuf+(row_num*decoder->ibpr);
png_progressive_combine_row(png_ptr, line, new_row);
}
else
line = new_row;
if (new_row) {
nscoord width;
decoder->mFrame->GetWidth(&width);
PRUint32 iwidth = width;
gfx_format format;
decoder->mFrame->GetFormat(&format);
PRUint8 *aptr, *cptr;
// The mac specific ifdefs in the code below are there to make sure we
// always fill in 4 byte pixels right now, which is what the mac always
// allocates for its pixel buffers in true color mode. This will change
// when we start storing images with color palettes when they don't need
// true color support (GIFs).
switch (format) {
case gfxIFormats::RGB:
case gfxIFormats::BGR:
#ifdef XP_MAC
cptr = decoder->colorLine;
for (PRUint32 x=0; x<iwidth; x++) {
*cptr++ = 0;
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
#else
decoder->mFrame->SetImageData((PRUint8*)line, bpr, row_num*bpr);
#endif
break;
case gfxIFormats::RGB_A1:
case gfxIFormats::BGR_A1:
{
cptr = decoder->colorLine;
aptr = decoder->alphaLine;
memset(aptr, 0, abpr);
for (PRUint32 x=0; x<iwidth; x++) {
#ifdef XP_MAC
*cptr++ = 0;
#endif
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
if (*line++) {
aptr[x>>3] |= 1<<(7-x&0x7);
}
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
}
break;
case gfxIFormats::RGB_A8:
case gfxIFormats::BGR_A8:
{
cptr = decoder->colorLine;
aptr = decoder->alphaLine;
for (PRUint32 x=0; x<iwidth; x++) {
#ifdef XP_MAC
*cptr++ = 0;
#endif
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
*aptr++ = *line++;
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
}
break;
case gfxIFormats::RGBA:
case gfxIFormats::BGRA:
#ifdef XP_MAC
{
cptr = decoder->colorLine;
aptr = decoder->alphaLine;
for (PRUint32 x=0; x<iwidth; x++) {
*cptr++ = 0;
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
*aptr++ = *line++;
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
}
#else
decoder->mFrame->SetImageData(line, bpr, row_num*bpr);
#endif
break;
}
nsRect r(0, row_num, width, 1);
decoder->mObserver->OnDataAvailable(nsnull, nsnull, decoder->mFrame, &r);
}
}
void
nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr)
{
/* libpng comments:
*
* this function is called when the whole image has been read,
* including any chunks after the image (up to and including
* the IEND). You will usually have the same info chunk as you
* had in the header, although some data may have been added
* to the comments and time fields.
*
* Most people won't do much here, perhaps setting a flag that
* marks the image as finished.
*/
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
if (decoder->mObserver) {
decoder->mObserver->OnStopFrame(nsnull, nsnull, decoder->mFrame);
decoder->mObserver->OnStopContainer(nsnull, nsnull, decoder->mImage);
decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
}

View File

@@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsPNGDecoder_h__
#define nsPNGDecoder_h__
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#include "nsCOMPtr.h"
#include "png.h"
#define NS_PNGDECODER_CID \
{ /* 36fa00c2-1dd2-11b2-be07-d16eeb4c50ed */ \
0x36fa00c2, \
0x1dd2, \
0x11b2, \
{0xbe, 0x07, 0xd1, 0x6e, 0xeb, 0x4c, 0x50, 0xed} \
}
class nsPNGDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsPNGDecoder();
virtual ~nsPNGDecoder();
PR_STATIC_CALLBACK(void)
info_callback(png_structp png_ptr, png_infop info_ptr);
PR_STATIC_CALLBACK(void)
row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass);
PR_STATIC_CALLBACK(void)
end_callback(png_structp png_ptr, png_infop info_ptr);
inline PRUint32 ProcessData(unsigned char *data, PRUint32 count);
public:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
png_structp mPNG;
png_infop mInfo;
PRUint8 *colorLine, *alphaLine;
PRUint8 *interlacebuf;
PRUint32 ibpr;
};
#endif // nsPNGDecoder_h__

View File

@@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsPNGDecoder.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPNGDecoder)
static nsModuleComponentInfo components[] =
{
{ "PNG decoder",
NS_PNGDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/png",
nsPNGDecoderConstructor, },
{ "PNG decoder",
NS_PNGDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/x-png",
nsPNGDecoderConstructor, },
};
NS_IMPL_NSGETMODULE("nsPNGDecoderModule", components)

View File

@@ -0,0 +1,42 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imgppm
LIBRARY_NAME = imgppm
IS_COMPONENT = 1
REQUIRES = xpcom layout necko gfx2 imglib2
CPPSRCS = nsPPMDecoder.cpp nsPPMFactory.cpp
EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,51 @@
#!nmake
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imgppm
LIBRARY_NAME = imgppm
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsPPMDecoder.obj \
.\$(OBJDIR)\nsPPMFactory.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,305 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
*/
#include "nsPPMDecoder.h"
#include "nsIInputStream.h"
#include "imgIContainer.h"
#include "imgIContainerObserver.h"
#include "nspr.h"
#include "nsIComponentManager.h"
#include "nsRect.h"
NS_IMPL_ISUPPORTS2(nsPPMDecoder, imgIDecoder, nsIOutputStream)
nsPPMDecoder::nsPPMDecoder()
{
NS_INIT_ISUPPORTS();
mDataReceived = 0;
mDataWritten = 0;
mDataLeft = 0;
mPrevData = nsnull;
}
nsPPMDecoder::~nsPPMDecoder()
{
}
/** imgIDecoder methods **/
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsPPMDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImage));
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame)
return NS_ERROR_FAILURE;
return NS_OK;
}
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsPPMDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
/* void close (); */
NS_IMETHODIMP nsPPMDecoder::Close()
{
if (mObserver) {
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
mObserver->OnStopContainer(nsnull, nsnull, mImage);
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
return NS_OK;
}
/* void flush (); */
NS_IMETHODIMP nsPPMDecoder::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsPPMDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static char *__itoa(int n)
{
char *s;
int i, j, sign, tmp;
/* check sign and convert to positive to stringify numbers */
if ( (sign = n) < 0)
n = -n;
i = 0;
s = (char*) malloc(sizeof(char));
/* grow string as needed to add numbers from powers of 10
* down till none left
*/
do
{
s = (char*) realloc(s, (i+1)*sizeof(char));
s[i++] = n % 10 + '0'; /* '0' or 30 is where ASCII numbers start */
s[i] = '\0';
}
while( (n /= 10) > 0);
/* tack on minus sign if we found earlier that this was negative */
if (sign < 0)
{
s = (char*) realloc(s, (i+1)*sizeof(char));
s[i++] = '-';
}
s[i] = '\0';
/* pop numbers (and sign) off of string to push back into right direction */
for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
return s;
}
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsPPMDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
nsresult rv;
char *buf = (char *)PR_Malloc(count + mDataLeft);
if (!buf)
return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
// read the data from the input stram...
PRUint32 readLen;
rv = inStr->Read(buf+mDataLeft, count, &readLen);
PRUint32 dataLen = readLen + mDataLeft;
if (mPrevData) {
strncpy(buf, mPrevData, mDataLeft);
PR_Free(mPrevData);
mPrevData = nsnull;
mDataLeft = 0;
}
char *data = buf;
if (NS_FAILED(rv)) return rv;
if (mDataReceived == 0) {
mObserver->OnStartDecode(nsnull, nsnull);
// Check the magic number
char type;
if ((sscanf(data, "P%c\n", &type) !=1) || (type != '6')) {
return NS_ERROR_FAILURE;
}
int i = 3;
data += i;
#if 0
// XXX
// Ignore comments
while ((input = fgetc(f)) == '#')
fgets(junk, 512, f);
ungetc(input, f);
#endif
// Read size
int w, h, mcv;
if (sscanf(data, "%d %d\n%d\n", &w, &h, &mcv) != 3) {
return NS_ERROR_FAILURE;
}
char *ws = __itoa(w), *hs = __itoa(h), *mcvs = __itoa(mcv);
int j = strlen(ws) + strlen(hs) + strlen(mcvs) + 3;
data += j;
// free(ws);
// free(hs);
// free(mcvs);
readLen -= i + j;
dataLen = readLen; // since this is the first pass, we don't have any data waiting that we need to keep track of
mImage->Init(w, h, mObserver);
if (mObserver)
mObserver->OnStartContainer(nsnull, nsnull, mImage);
mFrame->Init(0, 0, w, h, gfxIFormats::RGB);
mImage->AppendFrame(mFrame);
if (mObserver)
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
}
PRUint32 bpr;
nscoord width;
mFrame->GetImageBytesPerRow(&bpr);
mFrame->GetWidth(&width);
// XXX ceil?
PRUint32 real_bpr = width * 3;
PRUint32 i = 0;
PRUint32 rownum = mDataWritten / real_bpr; // XXX this better not have a decimal
PRUint32 wroteLen = 0;
if (readLen > real_bpr) {
do {
PRUint8 *line = (PRUint8*)data + i*real_bpr;
mFrame->SetImageData(line, real_bpr, (rownum++)*bpr);
nsRect r(0, rownum, width, 1);
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
wroteLen += real_bpr ;
i++;
} while(dataLen >= real_bpr * (i+1));
}
mDataReceived += readLen; // don't double count previous data that is in 'dataLen'
mDataWritten += wroteLen;
PRUint32 dataLeft = dataLen - wroteLen;
if (dataLeft > 0) {
if (mPrevData) {
mPrevData = (char *)PR_Realloc(mPrevData, mDataLeft + dataLeft);
strncpy(mPrevData + mDataLeft, data+wroteLen, dataLeft);
mDataLeft += dataLeft;
} else {
mDataLeft = dataLeft;
mPrevData = (char *)PR_Malloc(mDataLeft);
strncpy(mPrevData, data+wroteLen, mDataLeft);
}
}
PR_FREEIF(buf);
return NS_OK;
}
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsPPMDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsPPMDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPPMDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsPPMDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPPMDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsPPMDecoder_h__
#define nsPPMDecoder_h__
#include "imgIDecoder.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#define NS_PPMDECODER_CID \
{ /* e90bfa06-1dd1-11b2-8217-f38fe5d431a2 */ \
0xe90bfa06, \
0x1dd1, \
0x11b2, \
{0x82, 0x17, 0xf3, 0x8f, 0xe5, 0xd4, 0x31, 0xa2} \
}
class nsPPMDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsPPMDecoder();
virtual ~nsPPMDecoder();
private:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
PRUint32 mDataReceived;
PRUint32 mDataWritten;
PRUint32 mDataLeft;
char *mPrevData;
};
#endif // nsPPMDecoder_h__

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsPPMDecoder.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPPMDecoder)
static nsModuleComponentInfo components[] =
{
{ "ppm decoder",
NS_PPMDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/x-portable-pixmap",
nsPPMDecoderConstructor, },
};
NS_IMPL_NSGETMODULE("nsPPMDecoderModule", components)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,25 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..
DIRS = public src decoders
!include $(DEPTH)\config\rules.mak

View File

@@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "prlog.h"
#include "nsString.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo *gImgLog;
class LogScope {
public:
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s {ENTER}\n",
mFrom, mFunc.get()));
}
/* const char * constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, const char *paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=\"%s\") {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
/* void ptr constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, const void *paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=%p) {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
/* PRInt32 constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, PRInt32 paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=\"%d\") {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
/* PRUint32 constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, PRUint32 paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=\"%d\") {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
~LogScope() {
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s {EXIT}\n",
mFrom, mFunc.get()));
}
private:
PRLogModuleInfo *mLog;
void *mFrom;
nsCAutoString mFunc;
};
#define LOG_SCOPE(l, s) \
LogScope LOG_SCOPE_TMP_VAR ##__LINE__ (l, \
NS_STATIC_CAST(void *, this), \
NS_LITERAL_CSTRING(s))
#define LOG_SCOPE_WITH_PARAM(l, s, pn, pv) \
LogScope LOG_SCOPE_TMP_VAR ##__LINE__ (l, \
NS_STATIC_CAST(void *, this), \
NS_LITERAL_CSTRING(s), \
NS_LITERAL_CSTRING(pn), pv)
#else
#define LOG_SCOPE(l, s)
#define LOG_SCOPE_WITH_PARAM(l, s, pn, pv)
#endif

View File

@@ -0,0 +1 @@
ImageLogging.h

View File

@@ -0,0 +1,6 @@
imgIContainer.idl
imgIContainerObserver.idl
imgIDecoder.idl
imgIDecoderObserver.idl
imgILoader.idl
imgIRequest.idl

View File

@@ -0,0 +1,41 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imglib2
EXPORTS = ImageLogging.h
XPIDLSRCS = imgIContainer.idl \
imgIContainerObserver.idl \
imgIDecoder.idl \
imgIDecoderObserver.idl \
imgILoader.idl \
imgIRequest.idl
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,109 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "gfxtypes.idl"
#include "gfxIFormats.idl"
interface gfxIImageFrame;
interface nsIEnumerator;
interface imgIContainerObserver;
/**
* gfxIImageContainer interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see "gfx2"
*/
[scriptable, uuid(5e8405a4-1dd2-11b2-8385-bc8e3446cad3)]
interface imgIContainer : nsISupports
{
/**
* Create a new \a aWidth x \a aHeight sized image container.
*
* @param aWidth The width of the container in which all the
* gfxIImageFrame children will fit.
* @param aHeight The height of the container in which all the
* gfxIImageFrame children will fit.
* @param aObserver Observer to send animation notifications to.
*/
void init(in nscoord aWidth,
in nscoord aHeight,
in imgIContainerObserver aObserver);
/* this should probably be on the device context (or equiv) */
readonly attribute gfx_format preferredAlphaChannelFormat;
/**
* The width of the container rectangle.
*/
readonly attribute nscoord width;
/**
* The height of the container rectangle.
*/
readonly attribute nscoord height;
/**
* Get the current frame that would be drawn if the image was to be drawn now
*/
readonly attribute gfxIImageFrame currentFrame;
readonly attribute unsigned long numFrames;
gfxIImageFrame getFrameAt(in unsigned long index);
/**
* Adds \a item to the end of the list of frames.
* @param item frame to add.
*/
void appendFrame(in gfxIImageFrame item);
void removeFrame(in gfxIImageFrame item);
/* notification when the current frame is done decoding */
void endFrameDecode(in unsigned long framenumber, in unsigned long timeout);
/* notification that the entire image has been decoded */
void decodingComplete();
nsIEnumerator enumerate();
void clear();
void startAnimation();
void stopAnimation();
/* animation stuff */
/**
* number of times to loop the image.
* @note -1 means forever.
*/
attribute long loopCount;
};

View File

@@ -0,0 +1,46 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "gfxtypes.idl"
%{C++
#include "nsRect.h"
%}
interface imgIContainer;
interface gfxIImageFrame;
/**
* imgIContainerObserver interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
*/
[uuid(153f1518-1dd2-11b2-b9cd-b16eb63e0471)]
interface imgIContainerObserver : nsISupports
{
[noscript] void frameChanged(in imgIContainer aContainer, in nsISupports aCX,
in gfxIImageFrame aFrame, in nsRect aDirtyRect);
};

View File

@@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "nsIOutputStream.idl"
#include "gfxtypes.idl"
interface imgIRequest;
/**
* imgIDecoder interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(9eebf43a-1dd1-11b2-953e-f1782f4cbad3)]
interface imgIDecoder : nsIOutputStream
{
/**
* Initalize an image decoder.
* @param aRequest the request that owns the decoder.
*
* @note The decode should QI \a aRequest to an imgIDecoderObserver
* and should send decoder notifications to the request.
* The decoder should always pass NULL as the first two parameters to
* all of the imgIDecoderObserver APIs.
*/
void init(in imgIRequest aRequest);
/// allows access to the nsIImage we have to put bits in to.
readonly attribute imgIRequest request;
};

View File

@@ -0,0 +1,80 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgIContainerObserver.idl"
interface imgIRequest;
interface imgIContainer;
interface gfxIImageFrame;
%{C++
#include "nsRect.h"
%}
/**
* imgIDecoderObserver interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(350163d2-1dd2-11b2-9e69-89959ecec1f3)]
interface imgIDecoderObserver : imgIContainerObserver
{
/**
* called as soon as the image begins getting decoded
*/
void onStartDecode(in imgIRequest aRequest, in nsISupports cx);
/**
* called once the image has been inited and therefore has a width and height
*/
void onStartContainer(in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer);
/**
* called when each frame is created
*/
void onStartFrame(in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame);
/**
* called when some part of the frame has new data in it
*/
[noscript] void onDataAvailable(in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame, [const] in nsRect aRect);
/**
* called when a frame is finished decoding
*/
void onStopFrame(in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame);
/**
* probably not needed. called right before onStopDecode
*/
void onStopContainer(in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer);
/**
* called when the decoder is dying off
*/
void onStopDecode(in imgIRequest aRequest, in nsISupports cx,
in nsresult status, in wstring statusArg);
};

View File

@@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "gfxtypes.idl"
interface imgIDecoderObserver;
interface imgIRequest;
interface nsIChannel;
interface nsILoadGroup;
interface nsIStreamListener;
interface nsIURI;
interface nsISimpleEnumerator;
/**
* imgILoader interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(4c8cf1e0-1dd2-11b2-aff9-c51cdbfcb6da)]
interface imgILoader : nsISupports
{
/**
* Start the load and decode of an image.
* @param uri the URI to load
* @param aObserver the observer
* @param cx some random data
*/
imgIRequest loadImage(in nsIURI uri, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports cx);
/**
* Start the load and decode of an image.
* @param uri the URI to load
* @param aObserver the observer
* @param cx some random data
*/
imgIRequest loadImageWithChannel(in nsIChannel aChannel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener aListener);
};

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "nsIRequest.idl"
interface imgIContainer;
interface imgIDecoderObserver;
interface nsIURI;
/**
* imgIRequest interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(ccf705f6-1dd1-11b2-82ef-e18eccf7f7ec)]
interface imgIRequest : nsIRequest
{
/**
* the image container...
* @return the image object associated with the request.
* @attention NEED DOCS
*/
readonly attribute imgIContainer image;
/**
* Bits set in the return value from imageStatus
* @name statusflags
*/
//@{
const long STATUS_NONE = 0x0;
const long STATUS_SIZE_AVAILABLE = 0x1;
const long STATUS_LOAD_COMPLETE = 0x2;
const long STATUS_ERROR = 0x4;
//@}
/**
* something
* @attention NEED DOCS
*/
readonly attribute unsigned long imageStatus;
readonly attribute nsIURI URI;
readonly attribute imgIDecoderObserver decoderObserver;
};
%{C++
/**
* imagelib specific nsresult success and error codes
*/
#define NS_IMAGELIB_SUCCESS_LOAD_FINISHED NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_IMGLIB, 0)
#define NS_IMAGELIB_ERROR_FAILURE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_IMGLIB, 5)
#define NS_IMAGELIB_ERROR_NO_DECODER NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_IMGLIB, 6)
%}

View File

@@ -0,0 +1,43 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH = ..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imglib2
XPIDL_MODULE = imglib2
EXPORTS = ImageLogging.h
XPIDLSRCS = \
.\imgIContainer.idl \
.\imgIContainerObserver.idl \
.\imgIDecoder.idl \
.\imgIDecoderObserver.idl \
.\imgILoader.idl \
.\imgIRequest.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,146 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "DummyChannel.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
NS_IMPL_ISUPPORTS1(DummyChannel, nsIChannel)
DummyChannel::DummyChannel(imgIRequest *aRequest, nsILoadGroup *aLoadGroup) :
mRequest(aRequest),
mLoadGroup(aLoadGroup),
mLoadFlags(nsIChannel::LOAD_NORMAL)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
DummyChannel::~DummyChannel()
{
/* destructor code */
}
/* attribute nsIURI originalURI; */
NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI * *aOriginalURI)
{
return mRequest->GetURI(aOriginalURI);
}
NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI * aOriginalURI)
{
return NS_ERROR_FAILURE;
}
/* attribute nsIURI URI; */
NS_IMETHODIMP DummyChannel::GetURI(nsIURI * *aURI)
{
return mRequest->GetURI(aURI);
}
NS_IMETHODIMP DummyChannel::SetURI(nsIURI * aURI)
{
return NS_ERROR_FAILURE;
}
/* attribute nsISupports owner; */
NS_IMETHODIMP DummyChannel::GetOwner(nsISupports * *aOwner)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::SetOwner(nsISupports * aOwner)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsILoadGroup loadGroup; */
NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
return NS_ERROR_FAILURE;
}
/* attribute nsLoadFlags loadAttributes; */
NS_IMETHODIMP DummyChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = mLoadFlags;
return NS_OK;
}
NS_IMETHODIMP DummyChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
mLoadFlags = aLoadAttributes;
return NS_OK;
}
/* attribute nsIInterfaceRequestor notificationCallbacks; */
NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks)
{
return NS_OK;
}
NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)
{
return NS_OK;
}
/* readonly attribute nsISupports securityInfo; */
NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute string contentType; */
NS_IMETHODIMP DummyChannel::GetContentType(char * *aContentType)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::SetContentType(const char * aContentType)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute long contentLength; */
NS_IMETHODIMP DummyChannel::GetContentLength(PRInt32 *aContentLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::SetContentLength(PRInt32 aContentLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIInputStream open (); */
NS_IMETHODIMP DummyChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void asyncOpen (in nsIStreamListener listener, in nsISupports ctxt); */
NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef DummyChannel_h__
#define DummyChannel_h__
#include "nsIChannel.h"
#include "nsIRequest.h"
#include "nsILoadGroup.h"
#include "imgIRequest.h"
#include "nsCOMPtr.h"
class DummyChannel : public nsIChannel
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICHANNEL
NS_FORWARD_NSIREQUEST(mRequest->)
DummyChannel(imgIRequest *aRequest, nsILoadGroup *aLoadGroup);
~DummyChannel();
private:
/* additional members */
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsLoadFlags mLoadFlags;
};
#endif

View File

@@ -0,0 +1,166 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "ImageCache.h"
#ifdef MOZ_NEW_CACHE
#include "prlog.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo *gImgLog;
#else
#define gImgLog
#endif
#include "nsXPIDLString.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsICache.h"
#include "nsICacheService.h"
#include "nsICacheSession.h"
#include "nsICacheEntryDescriptor.h"
static nsCOMPtr<nsICacheSession> gSession = nsnull;
ImageCache::ImageCache()
{
/* member initializers and constructor code */
}
ImageCache::~ImageCache()
{
/* destructor code */
}
void GetCacheSession(nsICacheSession **_retval)
{
if (!gSession) {
nsCOMPtr<nsICacheService> cacheService(do_GetService("@mozilla.org/network/cache-service;1"));
NS_ASSERTION(cacheService, "Unable to get the cache service");
cacheService->CreateSession("images", nsICache::NOT_STREAM_BASED, PR_FALSE, getter_AddRefs(gSession));
NS_ASSERTION(gSession, "Unable to create a cache session");
}
*_retval = gSession;
NS_IF_ADDREF(*_retval);
}
void ImageCache::Shutdown()
{
gSession = nsnull;
}
PRBool ImageCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("ImageCache::Put\n"));
nsresult rv;
nsCOMPtr<nsICacheSession> ses;
GetCacheSession(getter_AddRefs(ses));
nsXPIDLCString spec;
aKey->GetSpec(getter_Copies(spec));
nsCOMPtr<nsICacheEntryDescriptor> entry;
rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_WRITE, getter_AddRefs(entry));
if (!entry || NS_FAILED(rv))
return PR_FALSE;
entry->SetCacheElement(NS_STATIC_CAST(nsISupports *, NS_STATIC_CAST(imgIRequest*, request)));
entry->MarkValid();
*aEntry = entry;
NS_ADDREF(*aEntry);
return PR_TRUE;
}
PRBool ImageCache::Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("ImageCache::Get\n"));
nsresult rv;
nsCOMPtr<nsICacheSession> ses;
GetCacheSession(getter_AddRefs(ses));
nsXPIDLCString spec;
aKey->GetSpec(getter_Copies(spec));
nsCOMPtr<nsICacheEntryDescriptor> entry;
rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_READ, getter_AddRefs(entry));
if (!entry || NS_FAILED(rv))
return PR_FALSE;
nsCOMPtr<nsISupports> sup;
entry->GetCacheElement(getter_AddRefs(sup));
nsCOMPtr<imgIRequest> req(do_QueryInterface(sup));
*aRequest = NS_REINTERPRET_CAST(imgRequest*, req.get());
NS_IF_ADDREF(*aRequest);
*aEntry = entry;
NS_ADDREF(*aEntry);
return PR_TRUE;
}
PRBool ImageCache::Remove(nsIURI *aKey)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("ImageCache::Remove\n"));
nsresult rv;
nsCOMPtr<nsICacheSession> ses;
GetCacheSession(getter_AddRefs(ses));
nsXPIDLCString spec;
aKey->GetSpec(getter_Copies(spec));
nsCOMPtr<nsICacheEntryDescriptor> entry;
rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_READ, getter_AddRefs(entry));
if (!entry || NS_FAILED(rv))
return PR_FALSE;
entry->Doom();
return PR_TRUE;
}
#endif /* MOZ_NEW_CACHE */

View File

@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef ImageCache_h__
#define ImageCache_h__
#include "nsIURI.h"
#include "imgRequest.h"
#include "prtypes.h"
#ifdef MOZ_NEW_CACHE
#include "nsICacheEntryDescriptor.h"
#else
class nsICacheEntryDescriptor;
#endif
class ImageCache
{
public:
#ifdef MOZ_NEW_CACHE
ImageCache();
~ImageCache();
static void Shutdown(); // for use by the factory
/* additional members */
static PRBool Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry);
static PRBool Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry);
static PRBool Remove(nsIURI *aKey);
#else
ImageCache() { }
~ImageCache() { }
static void Shutdown() { }
/* additional members */
static PRBool Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry) {
return PR_FALSE;
}
static PRBool Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry) {
return PR_FALSE;
}
static PRBool Remove(nsIURI *aKey) {
return PR_FALSE;
}
#endif /* MOZ_NEW_CACHE */
};
#endif

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "imgContainer.h"
#include "imgLoader.h"
#include "imgRequest.h"
#include "imgRequestProxy.h"
#include "ImageCache.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(imgContainer)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgLoader)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequest)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy)
static nsModuleComponentInfo components[] =
{
{ "image container",
NS_IMGCONTAINER_CID,
"@mozilla.org/image/container;1",
imgContainerConstructor, },
{ "image loader",
NS_IMGLOADER_CID,
"@mozilla.org/image/loader;1",
imgLoaderConstructor, },
{ "image request",
NS_IMGREQUEST_CID,
"@mozilla.org/image/request/real;1",
imgRequestConstructor, },
{ "image request proxy",
NS_IMGREQUESTPROXY_CID,
"@mozilla.org/image/request/proxy;1",
imgRequestProxyConstructor, },
};
PR_STATIC_CALLBACK(void)
ImageModuleDestructor(nsIModule *self)
{
ImageCache::Shutdown();
}
NS_IMPL_NSGETMODULE_WITH_DTOR("nsImageLib2Module", components, ImageModuleDestructor)

View File

@@ -0,0 +1,49 @@
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imglib2
LIBRARY_NAME = imglib2
IS_COMPONENT = 1
REQUIRES = xpcom string necko nkcache layout timer gfx2
CPPSRCS = \
DummyChannel.cpp \
ImageCache.cpp \
ImageFactory.cpp \
imgContainer.cpp \
imgLoader.cpp \
imgRequest.cpp \
imgRequestProxy.cpp
EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,555 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Chris Saari <saari@netscape.com>
*/
#include "imgContainer.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
NS_IMPL_ISUPPORTS3(imgContainer, imgIContainer, nsITimerCallback,imgIDecoderObserver)
//******************************************************************************
imgContainer::imgContainer()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
mCurrentDecodingFrameIndex = 0;
mCurrentAnimationFrameIndex = 0;
mCurrentFrameIsFinishedDecoding = PR_FALSE;
mDoneDecoding = PR_FALSE;
mAnimating = PR_FALSE;
mObserver = nsnull;
}
//******************************************************************************
imgContainer::~imgContainer()
{
if (mTimer)
mTimer->Cancel();
/* destructor code */
mFrames.Clear();
}
//******************************************************************************
/* void init (in nscoord aWidth, in nscoord aHeight, in imgIContainerObserver aObserver); */
NS_IMETHODIMP imgContainer::Init(nscoord aWidth, nscoord aHeight, imgIContainerObserver *aObserver)
{
if (aWidth <= 0 || aHeight <= 0) {
NS_WARNING("error - negative image size\n");
return NS_ERROR_FAILURE;
}
mSize.SizeTo(aWidth, aHeight);
mObserver = getter_AddRefs(NS_GetWeakReference(aObserver));
return NS_OK;
}
//******************************************************************************
/* readonly attribute gfx_format preferredAlphaChannelFormat; */
NS_IMETHODIMP imgContainer::GetPreferredAlphaChannelFormat(gfx_format *aFormat)
{
/* default.. platform's should probably overwrite this */
*aFormat = gfxIFormats::RGB_A8;
return NS_OK;
}
//******************************************************************************
/* readonly attribute nscoord width; */
NS_IMETHODIMP imgContainer::GetWidth(nscoord *aWidth)
{
*aWidth = mSize.width;
return NS_OK;
}
//******************************************************************************
/* readonly attribute nscoord height; */
NS_IMETHODIMP imgContainer::GetHeight(nscoord *aHeight)
{
*aHeight = mSize.height;
return NS_OK;
}
//******************************************************************************
/* readonly attribute gfxIImageFrame currentFrame; */
NS_IMETHODIMP imgContainer::GetCurrentFrame(gfxIImageFrame * *aCurrentFrame)
{
if(mCompositingFrame)
return mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aCurrentFrame); // addrefs again
else
return this->GetFrameAt(mCurrentAnimationFrameIndex, aCurrentFrame);
}
//******************************************************************************
/* readonly attribute unsigned long numFrames; */
NS_IMETHODIMP imgContainer::GetNumFrames(PRUint32 *aNumFrames)
{
return mFrames.Count(aNumFrames);
}
//******************************************************************************
/* gfxIImageFrame getFrameAt (in unsigned long index); */
NS_IMETHODIMP imgContainer::GetFrameAt(PRUint32 index, gfxIImageFrame **_retval)
{
nsISupports *sup = mFrames.ElementAt(index); // addrefs
if (!sup)
return NS_ERROR_FAILURE;
nsresult rv;
rv = sup->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)_retval); // addrefs again
NS_RELEASE(sup);
return rv;
}
//******************************************************************************
/* void appendFrame (in gfxIImageFrame item); */
NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item)
{
// If we don't have a composite frame already allocated, make sure that our container
// size is the same the frame size. Otherwise, we'll either need the composite frame
// for animation compositing (GIF) or for filling in with a background color.
// XXX IMPORTANT: this means that the frame should be initialized BEFORE appending to container
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
if(!mCompositingFrame) {
nsRect frameRect;
item->GetRect(frameRect);
// We used to create a compositing frame if any frame was smaller than the logical
// image size. You could create a single frame that was 10x10 in the middle of
// an 20x20 logical screen and have the extra screen space filled by the image
// background color. However, it turns out that neither NS4.x nor IE correctly
// support this, and as a result there are many GIFs out there that look "wrong"
// when this is correctly supported. So for now, we only create a compositing frame
// if we have more than one frame in the image.
if(/*(frameRect.x != 0) ||
(frameRect.y != 0) ||
(frameRect.width != mSize.width) ||
(frameRect.height != mSize.height) ||*/
(numFrames >= 1)) // Not sure if I want to create a composite frame for every anim. Could be smarter.
{
mCompositingFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
mCompositingFrame->Init(0, 0, mSize.width, mSize.height, gfxIFormats::RGB);
nsCOMPtr<nsIImage> img(do_GetInterface(mCompositingFrame));
img->SetDecodedRect(0, 0, mSize.width, mSize.height);
nsCOMPtr<gfxIImageFrame> firstFrame;
this->GetFrameAt(0, getter_AddRefs(firstFrame));
firstFrame->DrawTo(mCompositingFrame, 0, 0, mSize.width, mSize.height);
}
}
// If this is our second frame, init a timer so we don't display
// the next frame until the delay timer has expired for the current
// frame.
if (!mTimer && (numFrames >= 1)) {
PRInt32 timeout;
nsCOMPtr<gfxIImageFrame> currentFrame;
this->GetFrameAt(mCurrentDecodingFrameIndex, getter_AddRefs(currentFrame));
currentFrame->GetTimeout(&timeout);
if (timeout != -1 &&
timeout >= 0) { // -1 means display this frame forever
if(mAnimating) {
// Since we have more than one frame we need a timer
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(
NS_STATIC_CAST(nsITimerCallback*, this),
timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
}
}
if (numFrames > 0) mCurrentDecodingFrameIndex++;
mCurrentFrameIsFinishedDecoding = PR_FALSE;
return mFrames.AppendElement(NS_STATIC_CAST(nsISupports*, item));
}
//******************************************************************************
/* void removeFrame (in gfxIImageFrame item); */
NS_IMETHODIMP imgContainer::RemoveFrame(gfxIImageFrame *item)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void endFrameDecode (in gfxIImageFrame item, in unsigned long timeout); */
NS_IMETHODIMP imgContainer::EndFrameDecode(PRUint32 aFrameNum, PRUint32 aTimeout)
{
// It is now okay to start the timer for the next frame in the animation
mCurrentFrameIsFinishedDecoding = PR_TRUE;
nsCOMPtr<gfxIImageFrame> currentFrame;
this->GetFrameAt(aFrameNum-1, getter_AddRefs(currentFrame));
currentFrame->SetTimeout(aTimeout);
if (!mTimer && mAnimating){
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
if (numFrames > 1) {
if (aTimeout != -1 &&
aTimeout >= 0) { // -1 means display this frame forever
mAnimating = PR_TRUE;
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this),
aTimeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
}
}
return NS_OK;
}
//******************************************************************************
/* void decodingComplete (); */
NS_IMETHODIMP imgContainer::DecodingComplete(void)
{
mDoneDecoding = PR_TRUE;
return NS_OK;
}
//******************************************************************************
/* nsIEnumerator enumerate (); */
NS_IMETHODIMP imgContainer::Enumerate(nsIEnumerator **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void clear (); */
NS_IMETHODIMP imgContainer::Clear()
{
return mFrames.Clear();
}
//******************************************************************************
/* void startAnimation () */
NS_IMETHODIMP imgContainer::StartAnimation()
{
mAnimating = PR_TRUE;
if (mTimer)
return NS_OK;
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
if (numFrames > 1) {
PRInt32 timeout;
nsCOMPtr<gfxIImageFrame> currentFrame;
this->GetCurrentFrame(getter_AddRefs(currentFrame));
if (currentFrame) {
currentFrame->GetTimeout(&timeout);
if (timeout != -1 &&
timeout >= 0) { // -1 means display this frame forever
mAnimating = PR_TRUE;
if(!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this),
timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
} else {
// XXX hack.. the timer notify code will do the right thing, so just get that started
mAnimating = PR_TRUE;
if(!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this),
100, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
}
return NS_OK;
}
//******************************************************************************
/* void stopAnimation (); */
NS_IMETHODIMP imgContainer::StopAnimation()
{
mAnimating = PR_FALSE;
if (!mTimer)
return NS_OK;
mTimer->Cancel();
mTimer = nsnull;
// don't bother trying to change the frame (to 0, etc.) here.
// No one is listening.
return NS_OK;
}
//******************************************************************************
/* attribute long loopCount; */
NS_IMETHODIMP imgContainer::GetLoopCount(PRInt32 *aLoopCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP imgContainer::SetLoopCount(PRInt32 aLoopCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer)
{
NS_ASSERTION(mTimer == timer, "uh");
if(!mAnimating || !mTimer)
return;
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
if (!observer) {
// the imgRequest that owns us is dead, we should die now too.
this->StopAnimation();
return;
}
nsCOMPtr<gfxIImageFrame> nextFrame;
PRInt32 timeout = 100;
PRUint32 numFrames;
GetNumFrames(&numFrames);
if(!numFrames)
return;
// If we're done decoding the next frame, go ahead and display it now and reinit
// the timer with the next frame's delay time.
PRUint32 previousAnimationFrameIndex = mCurrentAnimationFrameIndex;
if (mCurrentFrameIsFinishedDecoding && !mDoneDecoding) {
// If we have the next frame in the sequence set the timer callback from it
GetFrameAt(mCurrentAnimationFrameIndex+1, getter_AddRefs(nextFrame));
if (nextFrame) {
// Go to next frame in sequence
nextFrame->GetTimeout(&timeout);
mCurrentAnimationFrameIndex++;
} else {
// twiddle our thumbs
GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame));
if(!nextFrame) return;
nextFrame->GetTimeout(&timeout);
}
} else if (mDoneDecoding){
if ((numFrames-1) == mCurrentAnimationFrameIndex) {
// Go back to the beginning of the animation
GetFrameAt(0, getter_AddRefs(nextFrame));
if(!nextFrame) return;
mCurrentAnimationFrameIndex = 0;
nextFrame->GetTimeout(&timeout);
} else {
mCurrentAnimationFrameIndex++;
GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame));
if(!nextFrame) return;
nextFrame->GetTimeout(&timeout);
}
} else {
GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame));
if(!nextFrame) return;
}
if(timeout >= 0)
mTimer->SetDelay(timeout);
else
this->StopAnimation();
nsRect dirtyRect;
// update the composited frame
if(mCompositingFrame && (previousAnimationFrameIndex != mCurrentAnimationFrameIndex)) {
nsCOMPtr<gfxIImageFrame> frameToUse;
DoComposite(getter_AddRefs(frameToUse), &dirtyRect, previousAnimationFrameIndex, mCurrentAnimationFrameIndex);
// do notification to FE to draw this frame, but hand it the compositing frame
observer->FrameChanged(this, nsnull, mCompositingFrame, &dirtyRect);
}
else {
nextFrame->GetRect(dirtyRect);
// do notification to FE to draw this frame
observer->FrameChanged(this, nsnull, nextFrame, &dirtyRect);
}
}
//******************************************************************************
// DoComposite gets called when the timer for animation get fired and we have to
// update the composited frame of the animation.
void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, PRInt32 aPrevFrame, PRInt32 aNextFrame)
{
NS_ASSERTION(aDirtyRect, "DoComposite aDirtyRect is null");
NS_ASSERTION(mCompositingFrame, "DoComposite mCompositingFrame is null");
*aFrameToUse = nsnull;
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
PRInt32 nextFrameIndex = aNextFrame;
PRInt32 prevFrameIndex = aPrevFrame;
if(nextFrameIndex >= numFrames) nextFrameIndex = numFrames-1;
if(prevFrameIndex >= numFrames) prevFrameIndex = numFrames-1;
nsCOMPtr<gfxIImageFrame> prevFrame;
this->GetFrameAt(prevFrameIndex, getter_AddRefs(prevFrame));
PRInt32 prevFrameDisposalMethod;
prevFrame->GetFrameDisposalMethod(&prevFrameDisposalMethod);
nsCOMPtr<gfxIImageFrame> nextFrame;
this->GetFrameAt(nextFrameIndex, getter_AddRefs(nextFrame));
PRInt32 x;
PRInt32 y;
PRInt32 width;
PRInt32 height;
nextFrame->GetX(&x);
nextFrame->GetY(&y);
nextFrame->GetWidth(&width);
nextFrame->GetHeight(&height);
switch (prevFrameDisposalMethod) {
default:
case 0: // DISPOSE_NOT_SPECIFIED
case 1: // DISPOSE_KEEP Leave previous frame in the framebuffer
mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again
//XXX blit into the composite frame too!!!
nextFrame->DrawTo(mCompositingFrame, x, y, width, height);
// we're drawing only the updated frame
(*aDirtyRect).x = x;
(*aDirtyRect).y = y;
(*aDirtyRect).width = width;
(*aDirtyRect).height = height;
break;
case 2: // DISPOSE_OVERWRITE_BGCOLOR Overwrite with background color
//XXX overwrite mCompositeFrame with background color
gfx_color backgroundColor;
nextFrame->GetBackgroundColor(&backgroundColor);
//XXX Do background color overwrite of mCompositeFrame here
// blit next frame into this clean slate
nextFrame->DrawTo(mCompositingFrame, x, y, width, height);
// In this case we need to blit the whole composite frame
(*aDirtyRect).x = 0;
(*aDirtyRect).y = 0;
(*aDirtyRect).width = mSize.width;
(*aDirtyRect).height = mSize.height;
mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again
break;
case 4: // DISPOSE_OVERWRITE_PREVIOUS Save-under
//XXX Reblit previous composite into frame buffer
//
(*aDirtyRect).x = 0;
(*aDirtyRect).y = 0;
(*aDirtyRect).width = mSize.width;
(*aDirtyRect).height = mSize.height;
break;
}
// Get the next frame's disposal method, if it is it DISPOSE_OVER, save off
// this mCompositeFrame for reblitting when this timer gets fired again and
// we
PRInt32 nextFrameDisposalMethod;
nextFrame->GetFrameDisposalMethod(&nextFrameDisposalMethod);
//XXX if(nextFrameDisposalMethod == 4)
// blit mPreviousCompositeFrame with this frame
}
//******************************************************************************
/* void onStartDecode (in imgIRequest aRequest, in nsISupports cx); */
NS_IMETHODIMP imgContainer::OnStartDecode(imgIRequest *aRequest, nsISupports *cx)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStartContainer (in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer); */
NS_IMETHODIMP imgContainer::OnStartContainer(imgIRequest *aRequest, nsISupports *cx, imgIContainer *aContainer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStartFrame (in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame); */
NS_IMETHODIMP imgContainer::OnStartFrame(imgIRequest *aRequest, nsISupports *cx, gfxIImageFrame *aFrame)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* [noscript] void onDataAvailable (in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame, [const] in nsRect aRect); */
NS_IMETHODIMP imgContainer::OnDataAvailable(imgIRequest *aRequest, nsISupports *cx, gfxIImageFrame *aFrame, const nsRect * aRect)
{
if(mCompositingFrame && !mCurrentDecodingFrameIndex) {
// Update the composite frame
PRInt32 x;
aFrame->GetX(&x);
aFrame->DrawTo(mCompositingFrame, x, aRect->y, aRect->width, aRect->height);
}
return NS_OK;
}
//******************************************************************************
/* void onStopFrame (in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame); */
NS_IMETHODIMP imgContainer::OnStopFrame(imgIRequest *aRequest, nsISupports *cx, gfxIImageFrame *aFrame)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStopContainer (in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer); */
NS_IMETHODIMP imgContainer::OnStopContainer(imgIRequest *aRequest, nsISupports *cx, imgIContainer *aContainer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStopDecode (in imgIRequest aRequest, in nsISupports cx, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgContainer::OnStopDecode(imgIRequest *aRequest, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* [noscript] void frameChanged (in imgIContainer aContainer, in nsISupports aCX, in gfxIImageFrame aFrame, in nsRect aDirtyRect); */
NS_IMETHODIMP imgContainer::FrameChanged(imgIContainer *aContainer, nsISupports *aCX, gfxIImageFrame *aFrame, nsRect * aDirtyRect)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Chris Saari <saari@netscape.com>
*/
#ifndef __imgContainer_h__
#define __imgContainer_h__
#include "imgIContainer.h"
#include "imgIContainerObserver.h"
#include "nsSize.h"
#include "nsSupportsArray.h"
#include "nsCOMPtr.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "nsWeakReference.h"
#define NS_IMGCONTAINER_CID \
{ /* 5e04ec5e-1dd2-11b2-8fda-c4db5fb666e0 */ \
0x5e04ec5e, \
0x1dd2, \
0x11b2, \
{0x8f, 0xda, 0xc4, 0xdb, 0x5f, 0xb6, 0x66, 0xe0} \
}
class imgContainer : public imgIContainer,
public nsITimerCallback,
public imgIDecoderObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGICONTAINER
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
NS_IMETHOD_(void) Notify(nsITimer *timer);
imgContainer();
virtual ~imgContainer();
private:
/* additional members */
nsSupportsArray mFrames;
nsSize mSize;
PRUint32 mCurrentDecodingFrameIndex; // 0 to numFrames-1
PRUint32 mCurrentAnimationFrameIndex; // 0 to numFrames-1
PRBool mCurrentFrameIsFinishedDecoding;
PRBool mDoneDecoding;
PRBool mAnimating;
nsWeakPtr mObserver;
// GIF specific bits
nsCOMPtr<nsITimer> mTimer;
// GIF animations will use the mCompositingFrame to composite images
// and just hand this back to the caller when it is time to draw the frame.
nsCOMPtr<gfxIImageFrame> mCompositingFrame;
// Private function for doing the frame compositing of animations and in cases
// where there is a backgound color and single frame placed withing a larger
// logical screen size. Smart GIF compressors may do this to save space.
void DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect,
PRInt32 aPrevFrame, PRInt32 aNextFrame);
};
#endif /* __imgContainer_h__ */

View File

@@ -0,0 +1,242 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgLoader.h"
#include "imgIRequest.h"
#include "nsIServiceManager.h"
#include "nsIChannel.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIStreamListener.h"
#include "nsIURI.h"
#include "imgRequest.h"
#include "imgRequestProxy.h"
#include "ImageCache.h"
#include "nsXPIDLString.h"
#include "nsCOMPtr.h"
#include "ImageLogging.h"
NS_IMPL_ISUPPORTS1(imgLoader, imgILoader)
imgLoader::imgLoader()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
imgLoader::~imgLoader()
{
/* destructor code */
}
/* imgIRequest loadImage (in nsIURI uri, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports cx); */
NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx, imgIRequest **_retval)
{
NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer");
if (!aURI)
return NS_ERROR_NULL_POINTER;
#if defined(PR_LOGGING)
nsXPIDLCString spec;
aURI->GetSpec(getter_Copies(spec));
LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::LoadImage", "aURI", spec.get());
#endif
imgRequest *request = nsnull;
#ifdef MOZ_NEW_CACHE
nsCOMPtr<nsICacheEntryDescriptor> entry;
ImageCache::Get(aURI, &request, getter_AddRefs(entry)); // addrefs request
if (request && entry && aLoadGroup) {
/* this isn't exactly what I want here. This code will re-doom every cache hit in a document while
it is force reloading. So for multiple copies of an image on a page, when you force reload, this
will cause you to get seperate loads for each copy of the image... this sucks.
*/
PRUint32 flags = 0;
PRBool doomRequest = PR_FALSE;
aLoadGroup->GetDefaultLoadAttributes(&flags);
if (flags & nsIChannel::FORCE_RELOAD)
doomRequest = PR_TRUE;
else {
nsCOMPtr<nsIRequest> r;
aLoadGroup->GetDefaultLoadRequest(getter_AddRefs(r));
if (r) {
nsCOMPtr<nsIChannel> c(do_QueryInterface(r));
if (c) {
c->GetLoadAttributes(&flags);
if (flags & nsIChannel::FORCE_RELOAD)
doomRequest = PR_TRUE;
}
}
}
if (doomRequest) {
entry->Doom(); // doom this thing.
entry = nsnull;
NS_RELEASE(request);
request = nsnull;
}
}
#endif
if (!request) {
/* no request from the cache. do a new load */
LOG_SCOPE(gImgLog, "imgLoader::LoadImage |cache miss|");
nsCOMPtr<nsIIOService> ioserv(do_GetService("@mozilla.org/network/io-service;1"));
if (!ioserv) return NS_ERROR_FAILURE;
nsCOMPtr<nsIChannel> newChannel;
ioserv->NewChannelFromURI(aURI, getter_AddRefs(newChannel));
if (!newChannel) return NS_ERROR_FAILURE;
if (aLoadGroup) {
PRUint32 flags;
aLoadGroup->GetDefaultLoadAttributes(&flags);
newChannel->SetLoadAttributes(flags);
}
NS_NEWXPCOM(request, imgRequest);
if (!request) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(request);
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request));
#ifdef MOZ_NEW_CACHE
ImageCache::Put(aURI, request, getter_AddRefs(entry));
#endif
#ifdef MOZ_NEW_CACHE
request->Init(newChannel, entry);
#else
request->Init(newChannel, nsnull);
#endif
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen()\n", this));
// XXX are we calling this too early?
newChannel->AsyncOpen(NS_STATIC_CAST(nsIStreamListener *, request), nsnull);
} else {
/* request found in cache. use it */
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage |cache hit| [request=%p]\n",
this, request));
}
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- creating proxy request.\n", this));
imgRequestProxy *proxyRequest;
NS_NEWXPCOM(proxyRequest, imgRequestProxy);
if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(proxyRequest);
// init adds itself to imgRequest's list of observers
proxyRequest->Init(request, aLoadGroup, aObserver, cx);
NS_RELEASE(request);
*_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest);
NS_ADDREF(*_retval);
NS_RELEASE(proxyRequest);
return NS_OK;
}
/* imgIRequest loadImageWithChannel(in nsIChannel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */
NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderObserver *aObserver, nsISupports *cx, nsIStreamListener **listener, imgIRequest **_retval)
{
NS_ASSERTION(channel, "imgLoader::LoadImageWithChannel -- NULL channel pointer");
imgRequest *request = nsnull;
nsCOMPtr<nsIURI> uri;
channel->GetOriginalURI(getter_AddRefs(uri));
#ifdef MOZ_NEW_CACHE
nsCOMPtr<nsICacheEntryDescriptor> entry;
ImageCache::Get(uri, &request, getter_AddRefs(entry)); // addrefs request
#endif
if (request) {
// we have this in our cache already.. cancel the current (document) load
// XXX
// if *listener is null when we return here, the caller should probably cancel
// the channel instead of us doing it here.
channel->Cancel(NS_BINDING_ABORTED); // this should fire an OnStopRequest
*listener = nsnull; // give them back a null nsIStreamListener
} else {
NS_NEWXPCOM(request, imgRequest);
if (!request) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(request);
#ifdef MOZ_NEW_CACHE
ImageCache::Put(uri, request, getter_AddRefs(entry));
#endif
#ifdef MOZ_NEW_CACHE
request->Init(channel, entry);
#else
request->Init(channel, nsnull);
#endif
*listener = NS_STATIC_CAST(nsIStreamListener*, request);
NS_IF_ADDREF(*listener);
}
imgRequestProxy *proxyRequest;
NS_NEWXPCOM(proxyRequest, imgRequestProxy);
if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(proxyRequest);
// init adds itself to imgRequest's list of observers
proxyRequest->Init(request, nsnull, aObserver, cx);
NS_RELEASE(request);
*_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest);
NS_ADDREF(*_retval);
NS_RELEASE(proxyRequest);
return NS_OK;
}

View File

@@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgILoader.h"
#ifdef LOADER_THREADSAFE
#include "prlock.h"
#endif
#define NS_IMGLOADER_CID \
{ /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */ \
0x9f6a0d2e, \
0x1dd1, \
0x11b2, \
{0xa5, 0xb8, 0x95, 0x1f, 0x13, 0xc8, 0x46, 0xf7} \
}
class imgLoader : public imgILoader
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGILOADER
imgLoader();
virtual ~imgLoader();
private:
};

View File

@@ -0,0 +1,821 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgRequest.h"
#include "nsIAtom.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsIHTTPChannel.h"
#include "nsIInputStream.h"
#include "imgILoader.h"
#include "nsIComponentManager.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "gfxIImageFrame.h"
#ifdef MOZ_NEW_CACHE
#include "nsICachingChannel.h"
#endif
#include "ImageCache.h"
#include "ImageLogging.h"
#if defined(PR_LOGGING)
PRLogModuleInfo *gImgLog = PR_NewLogModule("imgRequest");
#endif
NS_IMPL_ISUPPORTS7(imgRequest, imgIRequest, nsIRequest,
imgIDecoderObserver, imgIContainerObserver,
nsIStreamListener, nsIStreamObserver,
nsISupportsWeakReference)
imgRequest::imgRequest() :
mObservers(0), mLoading(PR_FALSE), mProcessing(PR_FALSE), mStatus(imgIRequest::STATUS_NONE), mState(0)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
imgRequest::~imgRequest()
{
/* destructor code */
}
nsresult imgRequest::Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheEntry)
{
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::Init\n", this));
NS_ASSERTION(!mImage, "imgRequest::Init -- Multiple calls to init");
NS_ASSERTION(aChannel, "imgRequest::Init -- No channel");
mChannel = aChannel;
#ifdef MOZ_NEW_CACHE
mCacheEntry = aCacheEntry;
#endif
// XXX do not init the image here. this has to be done from the image decoder.
mImage = do_CreateInstance("@mozilla.org/image/container;1");
return NS_OK;
}
nsresult imgRequest::AddObserver(imgIDecoderObserver *observer)
{
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddObserver", "observer", observer);
mObservers.AppendElement(NS_STATIC_CAST(void*, observer));
// OnStartDecode
if (mState & onStartDecode)
observer->OnStartDecode(nsnull, nsnull);
// OnStartContainer
if (mState & onStartContainer)
observer->OnStartContainer(nsnull, nsnull, mImage);
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
if (nframes > 0) {
nsCOMPtr<gfxIImageFrame> frame;
// Is this a single frame image?
if (nframes == 1) {
// Get the first frame
mImage->GetFrameAt(0, getter_AddRefs(frame));
NS_ASSERTION(frame, "GetFrameAt gave back a null frame!");
} else if (nframes > 1) {
/* multiple frames, we'll use the current one */
mImage->GetCurrentFrame(getter_AddRefs(frame));
NS_ASSERTION(frame, "GetCurrentFrame gave back a null frame!");
}
// OnStartFrame
observer->OnStartFrame(nsnull, nsnull, frame);
if (!(mState & onStopContainer)) {
// OnDataAvailable
nsRect r;
frame->GetRect(r); // XXX we shouldn't send the whole rect here
observer->OnDataAvailable(nsnull, nsnull, frame, &r);
} else {
// OnDataAvailable
nsRect r;
frame->GetRect(r); // We're done loading this image, send the the whole rect
observer->OnDataAvailable(nsnull, nsnull, frame, &r);
// OnStopFrame
observer->OnStopFrame(nsnull, nsnull, frame);
}
}
// OnStopContainer
if (mState & onStopContainer)
observer->OnStopContainer(nsnull, nsnull, mImage);
nsresult status;
if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE)
status = NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
else if (mStatus & imgIRequest::STATUS_ERROR)
status = NS_IMAGELIB_ERROR_FAILURE;
// OnStopDecode
if (mState & onStopDecode)
observer->OnStopDecode(nsnull, nsnull, status, nsnull);
if (mImage && (mObservers.Count() == 1)) {
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::AddObserver -- starting animation\n", this));
mImage->StartAnimation();
}
if (mState & onStopRequest) {
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(observer));
PR_ASSERT(observer);
ob->OnStopRequest(nsnull, nsnull, status, nsnull);
}
return NS_OK;
}
nsresult imgRequest::RemoveObserver(imgIDecoderObserver *observer, nsresult status)
{
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveObserver", "observer", observer);
mObservers.RemoveElement(NS_STATIC_CAST(void*, observer));
if (mObservers.Count() == 0) {
if (mImage) {
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
if (nframes > 1) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this));
mImage->StopAnimation();
}
}
if (mChannel && mLoading) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::RemoveObserver -- load in progress. canceling\n", this));
this->RemoveFromCache();
this->Cancel(NS_BINDING_ABORTED);
if (!(mState & onStopDecode)) {
// make sure that observer gets an onStopRequest message sent to it
observer->OnStopDecode(nsnull, nsnull, NS_IMAGELIB_ERROR_FAILURE, nsnull);
}
if (!(mState & onStopRequest)) {
// make sure that observer gets an onStopRequest message sent to it
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(observer));
PR_ASSERT(observer);
ob->OnStopRequest(nsnull, nsnull, NS_BINDING_ABORTED, nsnull);
}
}
}
return NS_OK;
}
PRBool imgRequest::RemoveFromCache()
{
LOG_SCOPE(gImgLog, "imgRequest::RemoveFromCache");
#ifdef MOZ_NEW_CACHE
if (mCacheEntry) {
mCacheEntry->Doom();
mCacheEntry = nsnull;
} else {
NS_WARNING("imgRequest::RemoveFromCache -- no entry!");
}
#endif
return PR_TRUE;
}
/** nsIRequest / imgIRequest methods **/
/* readonly attribute wstring name; */
NS_IMETHODIMP imgRequest::GetName(PRUnichar * *aName)
{
NS_NOTYETIMPLEMENTED("imgRequest::GetName");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean isPending (); */
NS_IMETHODIMP imgRequest::IsPending(PRBool *_retval)
{
NS_NOTYETIMPLEMENTED("imgRequest::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsresult status; */
NS_IMETHODIMP imgRequest::GetStatus(nsresult *aStatus)
{
NS_NOTYETIMPLEMENTED("imgRequest::GetStatus");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void cancel (in nsresult status); */
NS_IMETHODIMP imgRequest::Cancel(nsresult status)
{
LOG_SCOPE(gImgLog, "imgRequest::Cancel");
if (mImage) {
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
if (nframes > 1) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this));
mImage->StopAnimation();
}
}
if (mChannel && mLoading)
mChannel->Cancel(NS_BINDING_ABORTED); // should prolly use status here
return NS_OK;
}
/* void suspend (); */
NS_IMETHODIMP imgRequest::Suspend()
{
NS_NOTYETIMPLEMENTED("imgRequest::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void resume (); */
NS_IMETHODIMP imgRequest::Resume()
{
NS_NOTYETIMPLEMENTED("imgRequest::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
}
/** imgIRequest methods **/
/* readonly attribute imgIContainer image; */
NS_IMETHODIMP imgRequest::GetImage(imgIContainer * *aImage)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::GetImage\n", this));
*aImage = mImage;
NS_IF_ADDREF(*aImage);
return NS_OK;
}
/* readonly attribute unsigned long imageStatus; */
NS_IMETHODIMP imgRequest::GetImageStatus(PRUint32 *aStatus)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::GetImageStatus\n", this));
*aStatus = mStatus;
return NS_OK;
}
/* readonly attribute nsIURI URI; */
NS_IMETHODIMP imgRequest::GetURI(nsIURI **aURI)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::GetURI\n", this));
if (mChannel)
return mChannel->GetOriginalURI(aURI);
else if (mURI) {
*aURI = mURI;
NS_ADDREF(*aURI);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
/* readonly attribute imgIDecoderObserver decoderObserver; */
NS_IMETHODIMP imgRequest::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver)
{
return NS_ERROR_FAILURE;
}
/** imgIContainerObserver methods **/
/* [noscript] void frameChanged (in imgIContainer container, in nsISupports cx, in gfxIImageFrame newframe, in nsRect dirtyRect); */
NS_IMETHODIMP imgRequest::FrameChanged(imgIContainer *container, nsISupports *cx, gfxIImageFrame *newframe, nsRect * dirtyRect)
{
LOG_SCOPE(gImgLog, "imgRequest::FrameChanged");
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->FrameChanged(container, cx, newframe, dirtyRect);
}
return NS_OK;
}
/** imgIDecoderObserver methods **/
/* void onStartDecode (in imgIRequest request, in nsISupports cx); */
NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request, nsISupports *cx)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartDecode");
mState |= onStartDecode;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStartDecode(request, cx);
}
return NS_OK;
}
/* void onStartContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartContainer");
mState |= onStartContainer;
mStatus |= imgIRequest::STATUS_SIZE_AVAILABLE;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStartContainer(request, cx, image);
}
return NS_OK;
}
/* void onStartFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartFrame");
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStartFrame(request, cx, frame);
}
return NS_OK;
}
/* [noscript] void onDataAvailable (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame, [const] in nsRect rect); */
NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame, const nsRect * rect)
{
LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable");
nsCOMPtr<imgIDecoderObserver> container = do_QueryInterface(mImage);
container->OnDataAvailable(request, cx, frame, rect);
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnDataAvailable(request, cx, frame, rect);
}
return NS_OK;
}
/* void onStopFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
NS_ASSERTION(frame, "imgRequest::OnStopFrame called with NULL frame");
LOG_SCOPE(gImgLog, "imgRequest::OnStopFrame");
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
#ifdef MOZ_NEW_CACHE
if (mCacheEntry) {
PRUint32 cacheSize = 0;
mCacheEntry->GetDataSize(&cacheSize);
PRUint32 imageSize = 0;
PRUint32 alphaSize = 0;
frame->GetImageDataLength(&imageSize);
frame->GetAlphaDataLength(&alphaSize);
mCacheEntry->SetDataSize(cacheSize + imageSize + alphaSize);
}
#endif
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStopFrame(request, cx, frame);
}
return NS_OK;
}
/* void onStopContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStopContainer");
mState |= onStopContainer;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStopContainer(request, cx, image);
}
return NS_OK;
}
/* void onStopDecode (in imgIRequest request, in nsISupports cx, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest, nsISupports *aCX, nsresult aStatus, const PRUnichar *aStatusArg)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStopDecode");
if (mState & onStopDecode) {
NS_WARNING("OnStopDecode called multiple times.");
return NS_OK;
}
mState |= onStopDecode;
if (!(mStatus & imgIRequest::STATUS_ERROR) && NS_FAILED(aStatus))
mStatus |= imgIRequest::STATUS_ERROR;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
nsresult status;
if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE)
status = NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
else if (mStatus & imgIRequest::STATUS_ERROR)
status = NS_IMAGELIB_ERROR_FAILURE;
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStopDecode(aRequest, aCX, status, aStatusArg);
}
return NS_OK;
}
/** nsIStreamObserver methods **/
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest");
NS_ASSERTION(!mDecoder, "imgRequest::OnStartRequest -- we already have a decoder");
NS_ASSERTION(!mLoading, "imgRequest::OnStartRequest -- we are loading again?");
/* set our loading flag to true */
mLoading = PR_TRUE;
/* notify our kids */
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *iob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (iob) {
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(iob));
if (ob) ob->OnStartRequest(aRequest, ctxt);
}
}
/* do our real work */
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
if (!mChannel) {
PR_LOG(gImgLog, PR_LOG_ALWAYS,
(" `-> Channel already stopped or no channel!?.\n"));
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIHTTPChannel> httpChannel(do_QueryInterface(chan));
if (httpChannel) {
PRUint32 httpStatus;
httpChannel->GetResponseStatus(&httpStatus);
if (httpStatus == 404) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnStartRequest -- http status = 404. canceling.\n", this));
mStatus |= imgIRequest::STATUS_ERROR;
this->Cancel(NS_BINDING_ABORTED);
this->RemoveFromCache();
return NS_BINDING_ABORTED;
}
}
/* get the expires info */
#if defined(MOZ_NEW_CACHE)
if (mCacheEntry) {
nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(chan));
if (cacheChannel) {
nsCOMPtr<nsISupports> cacheToken;
cacheChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (cacheToken) {
nsCOMPtr<nsICacheEntryDescriptor> entryDesc(do_QueryInterface(cacheToken));
if (entryDesc) {
PRUint32 expiration;
/* get the expiration time from the caching channel's token */
entryDesc->GetExpirationTime(&expiration);
/* set the expiration time on our entry */
mCacheEntry->SetExpirationTime(expiration);
}
}
}
}
#endif
return NS_OK;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status, const PRUnichar *statusArg)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnStopRequest\n", this));
NS_ASSERTION(mChannel && mLoading, "imgRequest::OnStopRequest -- received multiple OnStopRequest");
mState |= onStopRequest;
/* set our loading flag to false */
mLoading = PR_FALSE;
/* set our processing flag to false */
mProcessing = PR_FALSE;
#ifdef MOZ_NEW_CACHE
/* break the cycle from the cache entry. */
mCacheEntry = nsnull;
#endif
if (NS_FAILED(status)) {
mStatus |= imgIRequest::STATUS_ERROR;
this->RemoveFromCache();
this->Cancel(status); // stops animations
} else {
mStatus |= imgIRequest::STATUS_LOAD_COMPLETE;
}
mChannel->GetOriginalURI(getter_AddRefs(mURI));
mChannel = nsnull; // we no longer need the channel
if (mDecoder) {
mDecoder->Flush();
mDecoder->Close();
mDecoder = nsnull; // release the decoder so that it can rest peacefully ;)
}
/* notify the kids */
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
void *item = NS_STATIC_CAST(void *, mObservers[i]);
if (item) {
imgIDecoderObserver *iob = NS_STATIC_CAST(imgIDecoderObserver*, item);
if (iob) {
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(iob));
if (ob) ob->OnStopRequest(aRequest, ctxt, status, statusArg);
}
}
}
// if there was an error loading the image, (mState & onStopDecode) won't be true.
// Send an onStopDecode message
if (!(mState & onStopDecode)) {
this->OnStopDecode(nsnull, nsnull, status, statusArg);
}
return NS_OK;
}
/* prototype for this defined below */
static NS_METHOD sniff_mimetype_callback(nsIInputStream* in, void* closure, const char* fromRawSegment,
PRUint32 toOffset, PRUint32 count, PRUint32 *writeCount);
/** nsIStreamListener methods **/
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnDataAvailable\n", this));
NS_ASSERTION(mChannel, "imgRequest::OnDataAvailable -- no channel!");
if (!mProcessing) {
/* set our processing flag to true if this is the first OnDataAvailable() */
mProcessing = PR_TRUE;
/* look at the first few bytes and see if we can tell what the data is from that
* since servers tend to lie. :(
*/
PRUint32 out;
inStr->ReadSegments(sniff_mimetype_callback, this, count, &out);
#ifdef NS_DEBUG
/* NS_WARNING if the content type from the channel isn't the same if the sniffing */
#endif
if (!mContentType.get()) {
nsXPIDLCString contentType;
nsresult rv = mChannel->GetContentType(getter_Copies(contentType));
if (NS_FAILED(rv)) {
PR_LOG(gImgLog, PR_LOG_ERROR,
("[this=%p] imgRequest::OnStartRequest -- Content type unavailable from the channel\n",
this));
this->RemoveFromCache();
return NS_BINDING_ABORTED; //NS_BASE_STREAM_CLOSED;
}
mContentType = contentType;
}
#if defined(PR_LOGGING)
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnStartRequest -- Content type is %s\n", this, mContentType.get()));
#endif
nsCAutoString conid("@mozilla.org/image/decoder;2?type=");
conid += mContentType.get();
mDecoder = do_CreateInstance(conid);
if (!mDecoder) {
PR_LOG(gImgLog, PR_LOG_WARNING,
("[this=%p] imgRequest::OnStartRequest -- Decoder not available\n", this));
// no image decoder for this mimetype :(
this->Cancel(NS_BINDING_ABORTED);
this->RemoveFromCache();
// XXX notify the person that owns us now that wants the imgIContainer off of us?
return NS_IMAGELIB_ERROR_NO_DECODER;
}
mDecoder->Init(NS_STATIC_CAST(imgIRequest*, this));
}
if (!mDecoder) {
PR_LOG(gImgLog, PR_LOG_WARNING,
("[this=%p] imgRequest::OnDataAvailable -- no decoder\n", this));
return NS_BASE_STREAM_CLOSED;
}
PRUint32 wrote;
nsresult rv = mDecoder->WriteFrom(inStr, count, &wrote);
return NS_OK;
}
static NS_METHOD sniff_mimetype_callback(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount)
{
imgRequest *request = NS_STATIC_CAST(imgRequest*, closure);
NS_ASSERTION(request, "request is null!");
if (count > 0)
request->SniffMimeType(fromRawSegment, count);
*writeCount = 0;
return NS_ERROR_FAILURE;
}
void
imgRequest::SniffMimeType(const char *buf, PRUint32 len)
{
/* Is it a GIF? */
if (len >= 4 && !nsCRT::strncmp(buf, "GIF8", 4)) {
mContentType = NS_LITERAL_CSTRING("image/gif");
return;
}
/* or a PNG? */
if (len >= 4 && ((unsigned char)buf[0]==0x89 &&
(unsigned char)buf[1]==0x50 &&
(unsigned char)buf[2]==0x4E &&
(unsigned char)buf[3]==0x47))
{
mContentType = NS_LITERAL_CSTRING("image/png");
return;
}
/* maybe a JPEG (JFIF)? */
/* JFIF files start with SOI APP0 but older files can start with SOI DQT
* so we test for SOI followed by any marker, i.e. FF D8 FF
* this will also work for SPIFF JPEG files if they appear in the future.
*
* (JFIF is 0XFF 0XD8 0XFF 0XE0 <skip 2> 0X4A 0X46 0X49 0X46 0X00)
*/
if (len >= 3 &&
((unsigned char)buf[0])==0xFF &&
((unsigned char)buf[1])==0xD8 &&
((unsigned char)buf[2])==0xFF)
{
mContentType = NS_LITERAL_CSTRING("image/jpeg");
return;
}
/* or how about ART? */
/* ART begins with JG (4A 47). Major version offset 2.
* Minor version offset 3. Offset 4 must be NULL.
*/
if (len >= 5 &&
((unsigned char) buf[0])==0x4a &&
((unsigned char) buf[1])==0x47 &&
((unsigned char) buf[4])==0x00 )
{
mContentType = NS_LITERAL_CSTRING("image/x-jg");
return;
}
/* none of the above? I give up */
}

View File

@@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef imgRequest_h__
#define imgRequest_h__
#include "imgIRequest.h"
#include "nsIRunnable.h"
#include "nsIChannel.h"
#include "nsIURI.h"
#include "imgIContainer.h"
#include "imgIDecoder.h"
#include "imgIDecoderObserver.h"
#include "nsIStreamListener.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsWeakReference.h"
#include "nsString.h"
#ifdef MOZ_NEW_CACHE
#include "nsICacheEntryDescriptor.h"
#else
class nsICacheEntryDescriptor;
#endif
#define NS_IMGREQUEST_CID \
{ /* 9f733dd6-1dd1-11b2-8cdf-effb70d1ea71 */ \
0x9f733dd6, \
0x1dd1, \
0x11b2, \
{0x8c, 0xdf, 0xef, 0xfb, 0x70, 0xd1, 0xea, 0x71} \
}
enum {
onStartDecode = 0x1,
onStartContainer = 0x2,
onStopContainer = 0x4,
onStopDecode = 0x8,
onStopRequest = 0x16
};
class imgRequest : public imgIRequest,
public imgIDecoderObserver,
public nsIStreamListener,
public nsSupportsWeakReference
{
public:
imgRequest();
virtual ~imgRequest();
/* additional members */
nsresult Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheEntry);
nsresult AddObserver(imgIDecoderObserver *observer);
nsresult RemoveObserver(imgIDecoderObserver *observer, nsresult status);
PRBool RemoveFromCache();
void SniffMimeType(const char *buf, PRUint32 len);
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISTREAMOBSERVER
private:
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<imgIDecoder> mDecoder;
nsVoidArray mObservers;
PRBool mLoading;
PRBool mProcessing;
PRUint32 mStatus;
PRUint32 mState;
nsCString mContentType;
#ifdef MOZ_NEW_CACHE
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry; /* we hold on to this to this so long as we have observers */
#endif
};
#endif

View File

@@ -0,0 +1,316 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgRequestProxy.h"
#include "nsXPIDLString.h"
#include "nsIInputStream.h"
#include "imgILoader.h"
#include "nsIComponentManager.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "imgRequest.h"
#include "nsString.h"
#include "DummyChannel.h"
#include "nspr.h"
#include "ImageLogging.h"
NS_IMPL_ISUPPORTS5(imgRequestProxy, imgIRequest, nsIRequest, imgIDecoderObserver, imgIContainerObserver, nsIStreamObserver)
imgRequestProxy::imgRequestProxy() :
mCanceled(PR_FALSE)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
imgRequestProxy::~imgRequestProxy()
{
/* destructor code */
// XXX pav
// it isn't the job of the request proxy to cancel itself.
// if your object goes away and you want to cancel the load, then do it yourself.
// cancel here for now until i make this work right like the above comment
Cancel(NS_ERROR_FAILURE);
}
nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx)
{
PR_ASSERT(request);
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequestProxy::Init", "request", request);
mOwner = NS_STATIC_CAST(imgIRequest*, request);
mObserver = aObserver;
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
mContext = cx;
// XXX we should only create a channel, etc if the image isn't finished loading already.
nsISupports *inst = nsnull;
inst = new DummyChannel(this, aLoadGroup);
NS_ADDREF(inst);
nsresult res = inst->QueryInterface(NS_GET_IID(nsIChannel), getter_AddRefs(mDummyChannel));
NS_RELEASE(inst);
nsCOMPtr<nsILoadGroup> loadGroup;
mDummyChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->AddRequest(mDummyChannel, cx);
}
request->AddObserver(this);
return NS_OK;
}
/** nsIRequest / imgIRequest methods **/
/* readonly attribute wstring name; */
NS_IMETHODIMP imgRequestProxy::GetName(PRUnichar * *aName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean isPending (); */
NS_IMETHODIMP imgRequestProxy::IsPending(PRBool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsresult status; */
NS_IMETHODIMP imgRequestProxy::GetStatus(nsresult *aStatus)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void cancel (in nsresult status); */
NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
{
if (mCanceled)
return NS_ERROR_FAILURE;
LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
mCanceled = PR_TRUE;
NS_ASSERTION(mOwner, "canceling request proxy twice");
nsresult rv = NS_REINTERPRET_CAST(imgRequest*, mOwner.get())->RemoveObserver(this, status);
mOwner = nsnull;
return rv;
}
/* void suspend (); */
NS_IMETHODIMP imgRequestProxy::Suspend()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void resume (); */
NS_IMETHODIMP imgRequestProxy::Resume()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/** imgIRequest methods **/
/* readonly attribute imgIContainer image; */
NS_IMETHODIMP imgRequestProxy::GetImage(imgIContainer * *aImage)
{
if (!mOwner)
return NS_ERROR_FAILURE;
return mOwner->GetImage(aImage);
}
/* readonly attribute unsigned long imageStatus; */
NS_IMETHODIMP imgRequestProxy::GetImageStatus(PRUint32 *aStatus)
{
if (!mOwner) {
*aStatus = imgIRequest::STATUS_ERROR;
return NS_ERROR_FAILURE;
}
return mOwner->GetImageStatus(aStatus);
}
/* readonly attribute nsIURI URI; */
NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI)
{
if (!mOwner)
return NS_ERROR_FAILURE;
return mOwner->GetURI(aURI);
}
/* readonly attribute imgIDecoderObserver decoderObserver; */
NS_IMETHODIMP imgRequestProxy::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver)
{
*aDecoderObserver = mObserver;
NS_IF_ADDREF(*aDecoderObserver);
return NS_OK;
}
/** imgIContainerObserver methods **/
/* [noscript] void frameChanged (in imgIContainer container, in nsISupports cx, in gfxIImageFrame newframe, in nsRect dirtyRect); */
NS_IMETHODIMP imgRequestProxy::FrameChanged(imgIContainer *container, nsISupports *cx, gfxIImageFrame *newframe, nsRect * dirtyRect)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::FrameChanged\n", this));
if (mObserver)
mObserver->FrameChanged(container, mContext, newframe, dirtyRect);
return NS_OK;
}
/** imgIDecoderObserver methods **/
/* void onStartDecode (in imgIRequest request, in nsISupports cx); */
NS_IMETHODIMP imgRequestProxy::OnStartDecode(imgIRequest *request, nsISupports *cx)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStartDecode\n", this));
if (mObserver)
mObserver->OnStartDecode(this, mContext);
return NS_OK;
}
/* void onStartContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequestProxy::OnStartContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStartContainer\n", this));
if (mObserver)
mObserver->OnStartContainer(this, mContext, image);
return NS_OK;
}
/* void onStartFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequestProxy::OnStartFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStartFrame\n", this));
if (mObserver)
mObserver->OnStartFrame(this, mContext, frame);
return NS_OK;
}
/* [noscript] void onDataAvailable (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame, [const] in nsRect rect); */
NS_IMETHODIMP imgRequestProxy::OnDataAvailable(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame, const nsRect * rect)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnDataAvailable\n", this));
if (mObserver)
mObserver->OnDataAvailable(this, mContext, frame, rect);
return NS_OK;
}
/* void onStopFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequestProxy::OnStopFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStopFrame\n", this));
if (mObserver)
mObserver->OnStopFrame(this, mContext, frame);
return NS_OK;
}
/* void onStopContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequestProxy::OnStopContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStopContainer\n", this));
if (mObserver)
mObserver->OnStopContainer(this, mContext, image);
return NS_OK;
}
/* void onStopDecode (in imgIRequest request, in nsISupports cx, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgRequestProxy::OnStopDecode(imgIRequest *request, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStopDecode\n", this));
if (mObserver)
mObserver->OnStopDecode(this, mContext, status, statusArg);
return NS_OK;
}
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgRequestProxy::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
return NS_OK;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult statusCode, in wstring statusText); */
NS_IMETHODIMP imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode, const PRUnichar *statusText)
{
if (!mDummyChannel)
return NS_OK;
nsCOMPtr<nsILoadGroup> loadGroup;
mDummyChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->RemoveRequest(mDummyChannel, mContext, statusCode, statusText);
}
mDummyChannel = nsnull;
return NS_OK;
}

View File

@@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgRequest.h"
#include "imgIDecoderObserver.h"
#include "imgIContainer.h"
#include "imgIDecoder.h"
#include "nsIStreamObserver.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsCOMPtr.h"
#define NS_IMGREQUESTPROXY_CID \
{ /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \
0x20557898, \
0x1dd2, \
0x11b2, \
{0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \
}
class imgRequestProxy : public imgIRequest,
public imgIDecoderObserver,
public nsIStreamObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
NS_DECL_NSISTREAMOBSERVER
imgRequestProxy();
virtual ~imgRequestProxy();
/* additional members */
nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx);
private:
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<imgIRequest> mOwner;
nsCOMPtr<nsIChannel> mDummyChannel;
PRBool mCanceled;
};

View File

@@ -0,0 +1,56 @@
#!nmake
#
# 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 mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imglib2
LIBRARY_NAME = imglib2
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\DummyChannel.obj \
.\$(OBJDIR)\ImageCache.obj \
.\$(OBJDIR)\ImageFactory.obj \
.\$(OBJDIR)\imgContainer.obj \
.\$(OBJDIR)\imgLoader.obj \
.\$(OBJDIR)\imgRequest.obj \
.\$(OBJDIR)\imgRequestProxy.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,90 @@
?AddRef@imgRequestProxy@@UAGKXZ ; 143798
?Release@imgContainer@@UAGKXZ ; 120291
?OnDataAvailable@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@PBUnsRect@@@Z ; 84442
?QueryInterface@imgContainer@@UAGIABUnsID@@PAPAX@Z ; 76980
?OnDataAvailable@imgContainer@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@PBUnsRect@@@Z ; 75604
?OnDataAvailable@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@PBUnsRect@@@Z ; 75604
?AddRef@DummyChannel@@UAGKXZ ; 45629
?QueryInterface@DummyChannel@@UAGIABUnsID@@PAPAX@Z ; 45310
?GetImage@imgRequest@@UAGIPAPAVimgIContainer@@@Z ; 41814
?Release@DummyChannel@@UAGKXZ ; 41716
?GetImage@imgRequestProxy@@UAGIPAPAVimgIContainer@@@Z ; 40453
?GetFrameAt@imgContainer@@UAGIIPAPAVgfxIImageFrame@@@Z ; 39613
?GetHeight@imgContainer@@UAGIPAH@Z ; 32348
?Release@imgRequest@@UAGKXZ ; 31603
?AddRef@imgRequest@@UAGKXZ ; 31603
?GetNumFrames@imgContainer@@UAGIPAI@Z ; 28342
?GetImageStatus@imgRequestProxy@@UAGIPAI@Z ; 27464
?Release@imgRequestProxy@@UAGKXZ ; 23383
?GetCurrentFrame@imgContainer@@UAGIPAPAVgfxIImageFrame@@@Z ; 19319
?QueryInterface@imgRequest@@UAGIABUnsID@@PAPAX@Z ; 16120
?assign_assuming_AddRef@nsCOMPtr_base@@IAEXPAVnsISupports@@@Z ; 13764
?FrameChanged@imgRequestProxy@@UAGIPAVimgIContainer@@PAVnsISupports@@PAVgfxIImageFrame@@PAUnsRect@@@Z ; 13455
?QueryInterface@imgRequestProxy@@UAGIABUnsID@@PAPAX@Z ; 10170
?Notify@imgContainer@@UAGXPAVnsITimer@@@Z ; 9611
??0nsQueryReferent@@QAE@PAVnsIWeakReference@@PAI@Z ; 9611
?FrameChanged@imgRequest@@UAGIPAVimgIContainer@@PAVnsISupports@@PAVgfxIImageFrame@@PAUnsRect@@@Z ; 9609
?DoComposite@imgContainer@@AAEXPAPAVgfxIImageFrame@@PAUnsRect@@HH@Z ; 9608
?GetLoadAttributes@DummyChannel@@UAGIPAI@Z ; 8258
?Cancel@imgRequestProxy@@UAGII@Z ; 7509
?GetLoadGroup@DummyChannel@@UAGIPAPAVnsILoadGroup@@@Z ; 7456
?GetURI@imgRequest@@UAGIPAPAVnsIURI@@@Z ; 5395
?GetURI@imgRequestProxy@@UAGIPAPAVnsIURI@@@Z ; 5395
?GetCacheSession@@YAXPAPAVnsICacheSession@@@Z ; 5165
?GetWidth@imgContainer@@UAGIPAH@Z ; 4675
?Release@imgLoader@@UAGKXZ ; 3791
?AddObserver@imgRequest@@QAEIPAVimgIDecoderObserver@@@Z ; 3789
?Get@ImageCache@@SAHPAVnsIURI@@PAPAVimgRequest@@PAPAVnsICacheEntryDescriptor@@@Z ; 3789
?RemoveObserver@imgRequest@@QAEIPAVimgIDecoderObserver@@I@Z ; 3789
?Init@imgRequestProxy@@QAEIPAVimgRequest@@PAVnsILoadGroup@@PAVimgIDecoderObserver@@PAVnsISupports@@@Z ; 3789
?QueryInterface@imgLoader@@UAGIABUnsID@@PAPAX@Z ; 3789
??0imgRequestProxy@@QAE@XZ ; 3789
??0DummyChannel@@QAE@PAVimgIRequest@@PAVnsILoadGroup@@@Z ; 3789
?LoadImage@imgLoader@@UAGIPAVnsIURI@@PAVnsILoadGroup@@PAVimgIDecoderObserver@@PAVnsISupports@@PAPAVimgIRequest@@@Z ; 3789
??1imgRequestProxy@@UAE@XZ ; 3667
??1DummyChannel@@QAE@XZ ; 3667
??_EimgRequestProxy@@UAEPAXI@Z ; 3667
?OnStopRequest@imgRequestProxy@@UAGIPAVnsIRequest@@PAVnsISupports@@IPBG@Z ; 3667
?OnStopDecode@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@IPBG@Z ; 3652
?OnStartContainer@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 3652
?OnStopContainer@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 3652
?OnStartDecode@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@@Z ; 3652
?OnStopFrame@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 3491
?OnStartFrame@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 3491
?OnStartRequest@imgRequestProxy@@UAGIPAVnsIRequest@@PAVnsISupports@@@Z ; 2714
?OnStopFrame@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 2082
?AppendFrame@imgContainer@@UAGIPAVgfxIImageFrame@@@Z ; 2082
?OnStartFrame@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 2082
?EndFrameDecode@imgContainer@@UAGIII@Z ; 1996
?StartAnimation@imgContainer@@UAGIXZ ; 1747
?OnDataAvailable@imgRequest@@UAGIPAVnsIRequest@@PAVnsISupports@@PAVnsIInputStream@@II@Z ; 1415
??0imgContainer@@QAE@XZ ; 1376
??1imgRequest@@UAE@XZ ; 1376
?OnStopRequest@imgRequest@@UAGIPAVnsIRequest@@PAVnsISupports@@IPBG@Z ; 1376
?Init@imgRequest@@QAEIPAVnsIChannel@@PAVnsICacheEntryDescriptor@@@Z ; 1376
??1imgContainer@@UAE@XZ ; 1376
?Put@ImageCache@@SAHPAVnsIURI@@PAVimgRequest@@PAPAVnsICacheEntryDescriptor@@@Z ; 1376
??_GimgRequest@@UAEPAXI@Z ; 1376
??_EimgContainer@@UAEPAXI@Z ; 1376
??0imgRequest@@QAE@XZ ; 1376
?OnStartRequest@imgRequest@@UAGIPAVnsIRequest@@PAVnsISupports@@@Z ; 1367
?OnStartContainer@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 1361
?Init@imgContainer@@UAGIHHPAVimgIContainerObserver@@@Z ; 1361
?OnStartDecode@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@@Z ; 1361
?SniffMimeType@imgRequest@@QAEXPBDI@Z ; 1361
?OnStopContainer@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 1361
?OnStopDecode@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@IPBG@Z ; 1361
?GetContentType@DummyChannel@@UAGIPAPAD@Z ; 1275
?DecodingComplete@imgContainer@@UAGIXZ ; 1275
?Cancel@DummyChannel@@UAGII@Z ; 122
?StopAnimation@imgContainer@@UAGIXZ ; 121
?GetDecoderObserver@imgRequestProxy@@UAGIPAPAVimgIDecoderObserver@@@Z ; 84
??0nsGetInterface@@QAE@PAVnsISupports@@PAI@Z ; 77
_NSGetModule ; 1
??_EimgLoader@@UAEPAXI@Z ; 1
??1imgLoader@@UAE@XZ ; 1
?Shutdown@ImageCache@@SAXXZ ; 1
??0imgLoader@@QAE@XZ ; 1
?do_GetService@@YA?BVnsGetServiceByContractID@@PBDPAI@Z ; 1
?Cancel@imgRequest@@UAGII@Z ; 1
?RemoveFromCache@imgRequest@@QAEHXZ ; 1

View File

@@ -1,95 +0,0 @@
#! gmake
#
# ***** 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export
# On AIX 4.3, IBM xlC_r compiler (version 3.6.6) cannot compile
# pkcs11c.c in 64-bit mode for unknown reasons. A workaround is
# to compile it with optimizations turned on. (Bugzilla bug #63815)
ifeq ($(OS_TARGET)$(OS_RELEASE),AIX4.3)
ifeq ($(USE_64),1)
ifndef BUILD_OPT
$(OBJDIR)/pkcs11.o: pkcs11.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c -O2 $(CFLAGS) $<
$(OBJDIR)/pkcs11c.o: pkcs11c.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c -O2 $(CFLAGS) $<
endif
endif
endif

View File

@@ -1,107 +0,0 @@
#
# ***** 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 *****
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
CRYPTODIR=../freebl
ifdef MOZILLA_SECURITY_BUILD
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
CRYPTODIR=../crypto
endif
SQLITE_LIB = $(DIST)/lib/$(LIB_PREFIX)sqlite3.$(LIB_SUFFIX)
ifdef NSS_USE_SYTEM_SQLITE
SQLITE_LIB = -lsqlite3
endif
EXTRA_LIBS += \
$(CRYPTOLIB) \
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
$(SQLITE_LIB) \
$(NULL)
# can't do this in manifest.mn because OS_TARGET isn't defined there.
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
else # ! NS_USE_GCC
EXTRA_SHARED_LIBS += \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
$(NULL)
endif # NS_USE_GCC
else
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
EXTRA_SHARED_LIBS += \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
endif
ifeq ($(OS_TARGET),SunOS)
# The -R '$ORIGIN' linker option instructs this library to search for its
# dependencies in the same directory where it resides.
MKSHLIB += -R '$$ORIGIN'
OS_LIBS += -lbsm
endif
ifeq ($(OS_TARGET),WINCE)
DEFINES += -DDBM_USING_NSPR
endif
# indicates dependency on freebl static lib
$(SHARED_LIBRARY): $(CRYPTOLIB)

View File

@@ -1,641 +0,0 @@
/*
* ***** 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 Elliptic Curve Cryptography library.
*
* The Initial Developer of the Original Code is
* Sun Microsystems, Inc.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
*
* 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 NSS_ENABLE_ECC
#include "blapi.h"
#include "secoid.h"
#include "secitem.h"
#include "secerr.h"
#include "ec.h"
#include "ecl-curve.h"
#define CHECK_OK(func) if (func == NULL) goto cleanup
#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
/*
* Initializes a SECItem from a hexadecimal string
*
* Warning: This function ignores leading 00's, so any leading 00's
* in the hexadecimal string must be optional.
*/
static SECItem *
hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str)
{
int i = 0;
int byteval = 0;
int tmp = PORT_Strlen(str);
if ((tmp % 2) != 0) return NULL;
/* skip leading 00's unless the hex string is "00" */
while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
str += 2;
tmp -= 2;
}
item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2);
if (item->data == NULL) return NULL;
item->len = tmp/2;
while (str[i]) {
if ((str[i] >= '0') && (str[i] <= '9'))
tmp = str[i] - '0';
else if ((str[i] >= 'a') && (str[i] <= 'f'))
tmp = str[i] - 'a' + 10;
else if ((str[i] >= 'A') && (str[i] <= 'F'))
tmp = str[i] - 'A' + 10;
else
return NULL;
byteval = byteval * 16 + tmp;
if ((i % 2) != 0) {
item->data[i/2] = byteval;
byteval = 0;
}
i++;
}
return item;
}
/* Copy all of the fields from srcParams into dstParams
*/
SECStatus
EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams)
{
SECStatus rv = SECFailure;
dstParams->arena = arena;
dstParams->type = srcParams->type;
dstParams->fieldID.size = srcParams->fieldID.size;
dstParams->fieldID.type = srcParams->fieldID.type;
if (srcParams->fieldID.type == ec_field_GFp) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
&srcParams->fieldID.u.prime));
} else {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
&srcParams->fieldID.u.poly));
}
dstParams->fieldID.k1 = srcParams->fieldID.k1;
dstParams->fieldID.k2 = srcParams->fieldID.k2;
dstParams->fieldID.k3 = srcParams->fieldID.k3;
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a,
&srcParams->curve.a));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b,
&srcParams->curve.b));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed,
&srcParams->curve.seed));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base,
&srcParams->base));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order,
&srcParams->order));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding,
&srcParams->DEREncoding));
dstParams->name = srcParams->name;
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID,
&srcParams->curveOID));
dstParams->cofactor = srcParams->cofactor;
return SECSuccess;
cleanup:
return SECFailure;
}
static SECStatus
gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
{
SECStatus rv = SECFailure;
const ECCurveParams *curveParams;
/* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) goto cleanup;
params->name = name;
curveParams = ecCurve_map[params->name];
CHECK_OK(curveParams);
params->fieldID.size = curveParams->size;
params->fieldID.type = field_type;
if (field_type == ec_field_GFp) {
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime,
curveParams->irr));
} else {
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.poly,
curveParams->irr));
}
CHECK_OK(hexString2SECItem(params->arena, &params->curve.a,
curveParams->curvea));
CHECK_OK(hexString2SECItem(params->arena, &params->curve.b,
curveParams->curveb));
genenc[0] = '0';
genenc[1] = '4';
genenc[2] = '\0';
strcat(genenc, curveParams->genx);
strcat(genenc, curveParams->geny);
CHECK_OK(hexString2SECItem(params->arena, &params->base, genenc));
CHECK_OK(hexString2SECItem(params->arena, &params->order,
curveParams->order));
params->cofactor = curveParams->cofactor;
rv = SECSuccess;
cleanup:
return rv;
}
SECStatus
EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
ECParams *params)
{
SECStatus rv = SECFailure;
SECOidTag tag;
SECItem oid = { siBuffer, NULL, 0};
#if EC_DEBUG
int i;
printf("Encoded params in EC_DecodeParams: ");
for (i = 0; i < encodedParams->len; i++) {
printf("%02x:", encodedParams->data[i]);
}
printf("\n");
#endif
if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
(encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
};
oid.len = encodedParams->len - 2;
oid.data = encodedParams->data + 2;
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
params->arena = arena;
params->cofactor = 0;
params->type = ec_params_named;
params->name = ECCurve_noName;
/* For named curves, fill out curveOID */
params->curveOID.len = oid.len;
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
if (params->curveOID.data == NULL) goto cleanup;
memcpy(params->curveOID.data, oid.data, oid.len);
#if EC_DEBUG
printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
#endif
switch (tag) {
/* Binary curves */
case SEC_OID_ANSIX962_EC_C2PNB163V1:
/* Populate params for c2pnb163v1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB163V2:
/* Populate params for c2pnb163v2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB163V3:
/* Populate params for c2pnb163v3 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB176V1:
/* Populate params for c2pnb176v1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB191V1:
/* Populate params for c2tnb191v1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB191V2:
/* Populate params for c2tnb191v2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB191V3:
/* Populate params for c2tnb191v3 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB208W1:
/* Populate params for c2pnb208w1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB239V1:
/* Populate params for c2tnb239v1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB239V2:
/* Populate params for c2tnb239v2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB239V3:
/* Populate params for c2tnb239v3 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB272W1:
/* Populate params for c2pnb272w1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB304W1:
/* Populate params for c2pnb304w1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB359V1:
/* Populate params for c2tnb359v1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2PNB368W1:
/* Populate params for c2pnb368w1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m,
params) );
break;
case SEC_OID_ANSIX962_EC_C2TNB431R1:
/* Populate params for c2tnb431r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT113R1:
/* Populate params for sect113r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT113R2:
/* Populate params for sect113r2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT131R1:
/* Populate params for sect131r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT131R2:
/* Populate params for sect131r2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT163K1:
/* Populate params for sect163k1
* (the NIST K-163 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT163R1:
/* Populate params for sect163r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT163R2:
/* Populate params for sect163r2
* (the NIST B-163 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT193R1:
/* Populate params for sect193r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT193R2:
/* Populate params for sect193r2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT233K1:
/* Populate params for sect233k1
* (the NIST K-233 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT233R1:
/* Populate params for sect233r1
* (the NIST B-233 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT239K1:
/* Populate params for sect239k1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT283K1:
/* Populate params for sect283k1
* (the NIST K-283 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT283R1:
/* Populate params for sect283r1
* (the NIST B-283 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT409K1:
/* Populate params for sect409k1
* (the NIST K-409 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT409R1:
/* Populate params for sect409r1
* (the NIST B-409 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT571K1:
/* Populate params for sect571k1
* (the NIST K-571 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m,
params) );
break;
case SEC_OID_SECG_EC_SECT571R1:
/* Populate params for sect571r1
* (the NIST B-571 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m,
params) );
break;
/* Prime curves */
case SEC_OID_ANSIX962_EC_PRIME192V1:
/* Populate params for prime192v1 aka secp192r1
* (the NIST P-192 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp,
params) );
break;
case SEC_OID_ANSIX962_EC_PRIME192V2:
/* Populate params for prime192v2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp,
params) );
break;
case SEC_OID_ANSIX962_EC_PRIME192V3:
/* Populate params for prime192v3 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp,
params) );
break;
case SEC_OID_ANSIX962_EC_PRIME239V1:
/* Populate params for prime239v1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp,
params) );
break;
case SEC_OID_ANSIX962_EC_PRIME239V2:
/* Populate params for prime239v2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp,
params) );
break;
case SEC_OID_ANSIX962_EC_PRIME239V3:
/* Populate params for prime239v3 */
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp,
params) );
break;
case SEC_OID_ANSIX962_EC_PRIME256V1:
/* Populate params for prime256v1 aka secp256r1
* (the NIST P-256 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP112R1:
/* Populate params for secp112r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP112R2:
/* Populate params for secp112r2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP128R1:
/* Populate params for secp128r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP128R2:
/* Populate params for secp128r2 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP160K1:
/* Populate params for secp160k1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP160R1:
/* Populate params for secp160r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP160R2:
/* Populate params for secp160r1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP192K1:
/* Populate params for secp192k1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP224K1:
/* Populate params for secp224k1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP224R1:
/* Populate params for secp224r1
* (the NIST P-224 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP256K1:
/* Populate params for secp256k1 */
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP384R1:
/* Populate params for secp384r1
* (the NIST P-384 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
params) );
break;
case SEC_OID_SECG_EC_SECP521R1:
/* Populate params for secp521r1
* (the NIST P-521 curve)
*/
CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
params) );
break;
default:
break;
};
cleanup:
if (!params->cofactor) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
#if EC_DEBUG
printf("Unrecognized curve, returning NULL params\n");
#endif
}
return rv;
}
SECStatus
EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams)
{
PRArenaPool *arena;
ECParams *params;
SECStatus rv = SECFailure;
/* Initialize an arena for the ECParams structure */
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
return SECFailure;
params = (ECParams *)PORT_ArenaZAlloc(arena, sizeof(ECParams));
if (!params) {
PORT_FreeArena(arena, PR_TRUE);
return SECFailure;
}
/* Copy the encoded params */
SECITEM_AllocItem(arena, &(params->DEREncoding),
encodedParams->len);
memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
/* Fill out the rest of the ECParams structure based on
* the encoded params
*/
rv = EC_FillParams(arena, encodedParams, params);
if (rv == SECFailure) {
PORT_FreeArena(arena, PR_TRUE);
return SECFailure;
} else {
*ecparams = params;;
return SECSuccess;
}
}
#endif /* NSS_ENABLE_ECC */

View File

@@ -1,351 +0,0 @@
/* ***** 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 Network Security Services (NSS).
*
* The Initial Developer of the Original Code is
* Red Hat, Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* 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 ***** */
/*
* This file implements audit logging required by FIPS 140-2 Security
* Level 2.
*/
#include "prprf.h"
#include "softoken.h"
/*
* Print the value of the returned object handle in the output buffer
* on a successful return of the PKCS #11 function. If the PKCS #11
* function failed or the pointer to object handle is NULL (which is
* the case for C_DeriveKey with CKM_TLS_KEY_AND_MAC_DERIVE), an empty
* string is stored in the output buffer.
*
* out: the output buffer
* outlen: the length of the output buffer
* argName: the name of the "pointer to object handle" argument
* phObject: the pointer to object handle
* rv: the return value of the PKCS #11 function
*/
static void sftk_PrintReturnedObjectHandle(char *out, PRUint32 outlen,
const char *argName, CK_OBJECT_HANDLE_PTR phObject, CK_RV rv)
{
if ((rv == CKR_OK) && phObject) {
PR_snprintf(out, outlen,
" *%s=0x%08lX", argName, (PRUint32)*phObject);
} else {
PORT_Assert(outlen != 0);
out[0] = '\0';
}
}
/*
* MECHANISM_BUFSIZE needs to be large enough for sftk_PrintMechanism,
* which uses <= 49 bytes.
*/
#define MECHANISM_BUFSIZE 64
static void sftk_PrintMechanism(char *out, PRUint32 outlen,
CK_MECHANISM_PTR pMechanism)
{
if (pMechanism) {
/*
* If we change the format string, we need to make sure
* MECHANISM_BUFSIZE is still large enough. We allow
* 20 bytes for %p on a 64-bit platform.
*/
PR_snprintf(out, outlen, "%p {mechanism=0x%08lX, ...}",
pMechanism, (PRUint32)pMechanism->mechanism);
} else {
PR_snprintf(out, outlen, "%p", pMechanism);
}
}
void sftk_AuditCreateObject(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject, CK_RV rv)
{
char msg[256];
char shObject[32];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintReturnedObjectHandle(shObject, sizeof shObject,
"phObject", phObject, rv);
PR_snprintf(msg, sizeof msg,
"C_CreateObject(hSession=0x%08lX, pTemplate=%p, ulCount=%lu, "
"phObject=%p)=0x%08lX%s",
(PRUint32)hSession, pTemplate, (PRUint32)ulCount,
phObject, (PRUint32)rv, shObject);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditCopyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phNewObject, CK_RV rv)
{
char msg[256];
char shNewObject[32];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintReturnedObjectHandle(shNewObject, sizeof shNewObject,
"phNewObject", phNewObject, rv);
PR_snprintf(msg, sizeof msg,
"C_CopyObject(hSession=0x%08lX, hObject=0x%08lX, "
"pTemplate=%p, ulCount=%lu, phNewObject=%p)=0x%08lX%s",
(PRUint32)hSession, (PRUint32)hObject,
pTemplate, (PRUint32)ulCount, phNewObject, (PRUint32)rv, shNewObject);
sftk_LogAuditMessage(severity, msg);
}
/* WARNING: hObject has been destroyed and can only be printed. */
void sftk_AuditDestroyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_RV rv)
{
char msg[256];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg, sizeof msg,
"C_DestroyObject(hSession=0x%08lX, hObject=0x%08lX)=0x%08lX",
(PRUint32)hSession, (PRUint32)hObject, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditGetObjectSize(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize, CK_RV rv)
{
char msg[256];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg, sizeof msg,
"C_GetObjectSize(hSession=0x%08lX, hObject=0x%08lX, "
"pulSize=%p)=0x%08lX",
(PRUint32)hSession, (PRUint32)hObject,
pulSize, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditGetAttributeValue(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount, CK_RV rv)
{
char msg[256];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg, sizeof msg,
"C_GetAttributeValue(hSession=0x%08lX, hObject=0x%08lX, "
"pTemplate=%p, ulCount=%lu)=0x%08lX",
(PRUint32)hSession, (PRUint32)hObject,
pTemplate, (PRUint32)ulCount, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditSetAttributeValue(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount, CK_RV rv)
{
char msg[256];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg, sizeof msg,
"C_SetAttributeValue(hSession=0x%08lX, hObject=0x%08lX, "
"pTemplate=%p, ulCount=%lu)=0x%08lX",
(PRUint32)hSession, (PRUint32)hObject,
pTemplate, (PRUint32)ulCount, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditCryptInit(const char *opName, CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_RV rv)
{
char msg[256];
char mech[MECHANISM_BUFSIZE];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
PR_snprintf(msg, sizeof msg,
"C_%sInit(hSession=0x%08lX, pMechanism=%s, "
"hKey=0x%08lX)=0x%08lX",
opName, (PRUint32)hSession, mech,
(PRUint32)hKey, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditGenerateKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey, CK_RV rv)
{
char msg[256];
char mech[MECHANISM_BUFSIZE];
char shKey[32];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv);
PR_snprintf(msg, sizeof msg,
"C_GenerateKey(hSession=0x%08lX, pMechanism=%s, "
"pTemplate=%p, ulCount=%lu, phKey=%p)=0x%08lX%s",
(PRUint32)hSession, mech,
pTemplate, (PRUint32)ulCount, phKey, (PRUint32)rv, shKey);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditGenerateKeyPair(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
CK_OBJECT_HANDLE_PTR phPrivateKey, CK_RV rv)
{
char msg[512];
char mech[MECHANISM_BUFSIZE];
char shPublicKey[32];
char shPrivateKey[32];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
sftk_PrintReturnedObjectHandle(shPublicKey, sizeof shPublicKey,
"phPublicKey", phPublicKey, rv);
sftk_PrintReturnedObjectHandle(shPrivateKey, sizeof shPrivateKey,
"phPrivateKey", phPrivateKey, rv);
PR_snprintf(msg, sizeof msg,
"C_GenerateKeyPair(hSession=0x%08lX, pMechanism=%s, "
"pPublicKeyTemplate=%p, ulPublicKeyAttributeCount=%lu, "
"pPrivateKeyTemplate=%p, ulPrivateKeyAttributeCount=%lu, "
"phPublicKey=%p, phPrivateKey=%p)=0x%08lX%s%s",
(PRUint32)hSession, mech,
pPublicKeyTemplate, (PRUint32)ulPublicKeyAttributeCount,
pPrivateKeyTemplate, (PRUint32)ulPrivateKeyAttributeCount,
phPublicKey, phPrivateKey, (PRUint32)rv, shPublicKey, shPrivateKey);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditWrapKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
CK_ULONG_PTR pulWrappedKeyLen, CK_RV rv)
{
char msg[256];
char mech[MECHANISM_BUFSIZE];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
PR_snprintf(msg, sizeof msg,
"C_WrapKey(hSession=0x%08lX, pMechanism=%s, hWrappingKey=0x%08lX, "
"hKey=0x%08lX, pWrappedKey=%p, pulWrappedKeyLen=%p)=0x%08lX",
(PRUint32)hSession, mech, (PRUint32)hWrappingKey,
(PRUint32)hKey, pWrappedKey, pulWrappedKeyLen, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditUnwrapKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey, CK_RV rv)
{
char msg[256];
char mech[MECHANISM_BUFSIZE];
char shKey[32];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv);
PR_snprintf(msg, sizeof msg,
"C_UnwrapKey(hSession=0x%08lX, pMechanism=%s, "
"hUnwrappingKey=0x%08lX, pWrappedKey=%p, ulWrappedKeyLen=%lu, "
"pTemplate=%p, ulAttributeCount=%lu, phKey=%p)=0x%08lX%s",
(PRUint32)hSession, mech,
(PRUint32)hUnwrappingKey, pWrappedKey, (PRUint32)ulWrappedKeyLen,
pTemplate, (PRUint32)ulAttributeCount, phKey, (PRUint32)rv, shKey);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditDeriveKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey, CK_RV rv)
{
char msg[512];
char mech[MECHANISM_BUFSIZE];
char shKey[32];
char sTlsKeys[128];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
sftk_PrintMechanism(mech, sizeof mech, pMechanism);
sftk_PrintReturnedObjectHandle(shKey, sizeof shKey, "phKey", phKey, rv);
if ((rv == CKR_OK) &&
(pMechanism->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE)) {
CK_SSL3_KEY_MAT_PARAMS *param =
(CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
CK_SSL3_KEY_MAT_OUT *keymat = param->pReturnedKeyMaterial;
PR_snprintf(sTlsKeys, sizeof sTlsKeys,
" hClientMacSecret=0x%08lX hServerMacSecret=0x%08lX"
" hClientKey=0x%08lX hServerKey=0x%08lX",
(PRUint32)keymat->hClientMacSecret,
(PRUint32)keymat->hServerMacSecret,
(PRUint32)keymat->hClientKey,
(PRUint32)keymat->hServerKey);
} else {
sTlsKeys[0] = '\0';
}
PR_snprintf(msg, sizeof msg,
"C_DeriveKey(hSession=0x%08lX, pMechanism=%s, "
"hBaseKey=0x%08lX, pTemplate=%p, ulAttributeCount=%lu, "
"phKey=%p)=0x%08lX%s%s",
(PRUint32)hSession, mech,
(PRUint32)hBaseKey, pTemplate,(PRUint32)ulAttributeCount,
phKey, (PRUint32)rv, shKey, sTlsKeys);
sftk_LogAuditMessage(severity, msg);
}
void sftk_AuditDigestKey(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hKey, CK_RV rv)
{
char msg[256];
NSSAuditSeverity severity = (rv == CKR_OK) ?
NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
PR_snprintf(msg, sizeof msg,
"C_DigestKey(hSession=0x%08lX, hKey=0x%08lX)=0x%08lX",
(PRUint32)hSession, (PRUint32)hKey, (PRUint32)rv);
sftk_LogAuditMessage(severity, msg);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,80 +0,0 @@
#! gmake
#
# ***** 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export

View File

@@ -1,85 +0,0 @@
/* ***** 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 ***** */
/*
* cdbhdl.h - certificate database handle
* private to the certdb module
*
* $Id: cdbhdl.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
*/
#ifndef _CDBHDL_H_
#define _CDBHDL_H_
#include "nspr.h"
#include "mcom_db.h"
#include "pcertt.h"
#include "prtypes.h"
/*
* Handle structure for open certificate databases
*/
struct NSSLOWCERTCertDBHandleStr {
DB *permCertDB;
PZMonitor *dbMon;
PRBool dbVerify;
PRInt32 ref; /* reference count */
};
#ifdef DBM_USING_NSPR
#define NO_RDONLY PR_RDONLY
#define NO_RDWR PR_RDWR
#define NO_CREATE (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE)
#else
#define NO_RDONLY O_RDONLY
#define NO_RDWR O_RDWR
#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC)
#endif
typedef DB * (*rdbfunc)(const char *appName, const char *prefix,
const char *type, int flags);
typedef int (*rdbstatusfunc)(void);
#define RDB_FAIL 1
#define RDB_RETRY 2
DB * rdbopen(const char *appName, const char *prefix,
const char *type, int flags, int *status);
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
const void * appData);
SECStatus db_Copy(DB *dest,DB *src);
int db_InitComplete(DB *db);
#endif

View File

@@ -1,102 +0,0 @@
#
# ***** 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 *****
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
CRYPTODIR=../freebl
ifdef MOZILLA_SECURITY_BUILD
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
CRYPTODIR=../crypto
endif
EXTRA_LIBS += \
$(CRYPTOLIB) \
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
$(NULL)
# can't do this in manifest.mn because OS_TARGET isn't defined there.
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
else # ! NS_USE_GCC
EXTRA_SHARED_LIBS += \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
$(NULL)
endif # NS_USE_GCC
else
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
EXTRA_SHARED_LIBS += \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
endif
ifeq ($(OS_TARGET),SunOS)
# The -R '$ORIGIN' linker option instructs this library to search for its
# dependencies in the same directory where it resides.
MKSHLIB += -R '$$ORIGIN'
OS_LIBS += -lbsm
endif
ifeq ($(OS_TARGET),WINCE)
DEFINES += -DDBM_USING_NSPR
endif
# indicates dependency on freebl static lib
$(SHARED_LIBRARY): $(CRYPTOLIB)

View File

@@ -1,647 +0,0 @@
/* ***** 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 ***** */
/*
* Berkeley DB 1.85 Shim code to handle blobs.
*
* $Id: dbmshim.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $
*/
#include "mcom_db.h"
#include "secitem.h"
#include "nssb64.h"
#include "blapi.h"
#include "secerr.h"
#include "lgdb.h"
/*
* Blob block:
* Byte 0 CERTDB Version -+ -+
* Byte 1 certDBEntryTypeBlob | BLOB_HEAD_LEN |
* Byte 2 flags (always '0'); | |
* Byte 3 reserved (always '0'); -+ |
* Byte 4 LSB length | <--BLOB_LENGTH_START | BLOB_BUF_LEN
* Byte 5 . | |
* Byte 6 . | BLOB_LENGTH_LEN |
* Byte 7 MSB length | |
* Byte 8 blob_filename -+ -+ <-- BLOB_NAME_START |
* Byte 9 . | BLOB_NAME_LEN |
* . . | |
* Byte 37 . -+ -+
*/
#define DBS_BLOCK_SIZE (16*1024) /* 16 k */
#define DBS_MAX_ENTRY_SIZE (DBS_BLOCK_SIZE - (2048)) /* 14 k */
#define DBS_CACHE_SIZE DBS_BLOCK_SIZE*8
#define ROUNDDIV(x,y) (x+(y-1))/y
#define BLOB_HEAD_LEN 4
#define BLOB_LENGTH_START BLOB_HEAD_LEN
#define BLOB_LENGTH_LEN 4
#define BLOB_NAME_START BLOB_LENGTH_START+BLOB_LENGTH_LEN
#define BLOB_NAME_LEN 1+ROUNDDIV(SHA1_LENGTH,3)*4+1
#define BLOB_BUF_LEN BLOB_HEAD_LEN+BLOB_LENGTH_LEN+BLOB_NAME_LEN
/* a Shim data structure. This data structure has a db built into it. */
typedef struct DBSStr DBS;
struct DBSStr {
DB db;
char *blobdir;
int mode;
PRBool readOnly;
PRFileMap *dbs_mapfile;
unsigned char *dbs_addr;
PRUint32 dbs_len;
char staticBlobArea[BLOB_BUF_LEN];
};
/*
* return true if the Datablock contains a blobtype
*/
static PRBool
dbs_IsBlob(DBT *blobData)
{
unsigned char *addr = (unsigned char *)blobData->data;
if (blobData->size < BLOB_BUF_LEN) {
return PR_FALSE;
}
return addr && ((certDBEntryType) addr[1] == certDBEntryTypeBlob);
}
/*
* extract the filename in the blob of the real data set.
* This value is not malloced (does not need to be freed by the caller.
*/
static const char *
dbs_getBlobFileName(DBT *blobData)
{
char *addr = (char *)blobData->data;
return &addr[BLOB_NAME_START];
}
/*
* extract the size of the actual blob from the blob record
*/
static PRUint32
dbs_getBlobSize(DBT *blobData)
{
unsigned char *addr = (unsigned char *)blobData->data;
return (PRUint32)(addr[BLOB_LENGTH_START+3] << 24) |
(addr[BLOB_LENGTH_START+2] << 16) |
(addr[BLOB_LENGTH_START+1] << 8) |
addr[BLOB_LENGTH_START];
}
/* We are using base64 data for the filename, but base64 data can include a
* '/' which is interpreted as a path separator on many platforms. Replace it
* with an inocuous '-'. We don't need to convert back because we never actual
* decode the filename.
*/
static void
dbs_replaceSlash(char *cp, int len)
{
while (len--) {
if (*cp == '/') *cp = '-';
cp++;
}
}
/*
* create a blob record from a key, data and return it in blobData.
* NOTE: The data element is static data (keeping with the dbm model).
*/
static void
dbs_mkBlob(DBS *dbsp,const DBT *key, const DBT *data, DBT *blobData)
{
unsigned char sha1_data[SHA1_LENGTH];
char *b = dbsp->staticBlobArea;
PRUint32 length = data->size;
SECItem sha1Item;
b[0] = CERT_DB_FILE_VERSION; /* certdb version number */
b[1] = (char) certDBEntryTypeBlob; /* type */
b[2] = 0; /* flags */
b[3] = 0; /* reserved */
b[BLOB_LENGTH_START] = length & 0xff;
b[BLOB_LENGTH_START+1] = (length >> 8) & 0xff;
b[BLOB_LENGTH_START+2] = (length >> 16) & 0xff;
b[BLOB_LENGTH_START+3] = (length >> 24) & 0xff;
sha1Item.data = sha1_data;
sha1Item.len = SHA1_LENGTH;
SHA1_HashBuf(sha1_data,key->data,key->size);
b[BLOB_NAME_START]='b'; /* Make sure we start with a alpha */
NSSBase64_EncodeItem(NULL,&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1,&sha1Item);
b[BLOB_BUF_LEN-1] = 0;
dbs_replaceSlash(&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1);
blobData->data = b;
blobData->size = BLOB_BUF_LEN;
return;
}
/*
* construct a path to the actual blob. The string returned must be
* freed by the caller with PR_smprintf_free.
*
* Note: this file does lots of consistancy checks on the DBT. The
* routines that call this depend on these checks, so they don't worry
* about them (success of this routine implies a good blobdata record).
*/
static char *
dbs_getBlobFilePath(char *blobdir,DBT *blobData)
{
const char *name;
if (blobdir == NULL) {
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
return NULL;
}
if (!dbs_IsBlob(blobData)) {
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
return NULL;
}
name = dbs_getBlobFileName(blobData);
if (!name || *name == 0) {
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
return NULL;
}
return PR_smprintf("%s" PATH_SEPARATOR "%s", blobdir, name);
}
/*
* Delete a blob file pointed to by the blob record.
*/
static void
dbs_removeBlob(DBS *dbsp, DBT *blobData)
{
char *file;
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
if (!file) {
return;
}
PR_Delete(file);
PR_smprintf_free(file);
}
/*
* Directory modes are slightly different, the 'x' bit needs to be on to
* access them. Copy all the read bits to 'x' bits
*/
static int
dbs_DirMode(int mode)
{
int x_bits = (mode >> 2) & 0111;
return mode | x_bits;
}
/*
* write a data blob to it's file. blobdData is the blob record that will be
* stored in the database. data is the actual data to go out on disk.
*/
static int
dbs_writeBlob(DBS *dbsp, int mode, DBT *blobData, const DBT *data)
{
char *file = NULL;
PRFileDesc *filed;
PRStatus status;
int len;
int error = 0;
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
if (!file) {
goto loser;
}
if (PR_Access(dbsp->blobdir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
status = PR_MkDir(dbsp->blobdir,dbs_DirMode(mode));
if (status != PR_SUCCESS) {
goto loser;
}
}
filed = PR_OpenFile(file,PR_CREATE_FILE|PR_TRUNCATE|PR_WRONLY, mode);
if (filed == NULL) {
error = PR_GetError();
goto loser;
}
len = PR_Write(filed,data->data,data->size);
error = PR_GetError();
PR_Close(filed);
if (len < (int)data->size) {
goto loser;
}
PR_smprintf_free(file);
return 0;
loser:
if (file) {
PR_Delete(file);
PR_smprintf_free(file);
}
/* don't let close or delete reset the error */
PR_SetError(error,0);
return -1;
}
/*
* we need to keep a address map in memory between calls to DBM.
* remember what we have mapped can close it when we get another dbm
* call.
*
* NOTE: Not all platforms support mapped files. This code is designed to
* detect this at runtime. If map files aren't supported the OS will indicate
* this by failing the PR_Memmap call. In this case we emulate mapped files
* by just reading in the file into regular memory. We signal this state by
* making dbs_mapfile NULL and dbs_addr non-NULL.
*/
static void
dbs_freemap(DBS *dbsp)
{
if (dbsp->dbs_mapfile) {
PR_MemUnmap(dbsp->dbs_addr,dbsp->dbs_len);
PR_CloseFileMap(dbsp->dbs_mapfile);
dbsp->dbs_mapfile = NULL;
dbsp->dbs_addr = NULL;
dbsp->dbs_len = 0;
} else if (dbsp->dbs_addr) {
PORT_Free(dbsp->dbs_addr);
dbsp->dbs_addr = NULL;
dbsp->dbs_len = 0;
}
return;
}
static void
dbs_setmap(DBS *dbsp, PRFileMap *mapfile, unsigned char *addr, PRUint32 len)
{
dbsp->dbs_mapfile = mapfile;
dbsp->dbs_addr = addr;
dbsp->dbs_len = len;
}
/*
* platforms that cannot map the file need to read it into a temp buffer.
*/
static unsigned char *
dbs_EmulateMap(PRFileDesc *filed, int len)
{
unsigned char *addr;
PRInt32 dataRead;
addr = PORT_Alloc(len);
if (addr == NULL) {
return NULL;
}
dataRead = PR_Read(filed,addr,len);
if (dataRead != len) {
PORT_Free(addr);
if (dataRead > 0) {
/* PR_Read didn't set an error, we need to */
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
}
return NULL;
}
return addr;
}
/*
* pull a database record off the disk
* data points to the blob record on input and the real record (if we could
* read it) on output. if there is an error data is not modified.
*/
static int
dbs_readBlob(DBS *dbsp, DBT *data)
{
char *file = NULL;
PRFileDesc *filed = NULL;
PRFileMap *mapfile = NULL;
unsigned char *addr = NULL;
int error;
int len = -1;
file = dbs_getBlobFilePath(dbsp->blobdir, data);
if (!file) {
goto loser;
}
filed = PR_OpenFile(file,PR_RDONLY,0);
PR_smprintf_free(file); file = NULL;
if (filed == NULL) {
goto loser;
}
len = dbs_getBlobSize(data);
mapfile = PR_CreateFileMap(filed, len, PR_PROT_READONLY);
if (mapfile == NULL) {
/* USE PR_GetError instead of PORT_GetError here
* because we are getting the error from PR_xxx
* function */
if (PR_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
goto loser;
}
addr = dbs_EmulateMap(filed, len);
} else {
addr = PR_MemMap(mapfile, 0, len);
}
if (addr == NULL) {
goto loser;
}
PR_Close(filed);
dbs_setmap(dbsp,mapfile,addr,len);
data->data = addr;
data->size = len;
return 0;
loser:
/* preserve the error code */
error = PR_GetError();
if (mapfile) {
PR_CloseFileMap(mapfile);
}
if (filed) {
PR_Close(filed);
}
PR_SetError(error,0);
return -1;
}
/*
* actual DBM shims
*/
static int
dbs_get(const DB *dbs, const DBT *key, DBT *data, unsigned int flags)
{
int ret;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
ret = (* db->get)(db, key, data, flags);
if ((ret == 0) && dbs_IsBlob(data)) {
ret = dbs_readBlob(dbsp,data);
}
return(ret);
}
static int
dbs_put(const DB *dbs, DBT *key, const DBT *data, unsigned int flags)
{
DBT blob;
int ret = 0;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
/* If the db is readonly, just pass the data down to rdb and let it fail */
if (!dbsp->readOnly) {
DBT oldData;
int ret1;
/* make sure the current record is deleted if it's a blob */
ret1 = (*db->get)(db,key,&oldData,0);
if ((ret1 == 0) && flags == R_NOOVERWRITE) {
/* let DBM return the error to maintain consistancy */
return (* db->put)(db, key, data, flags);
}
if ((ret1 == 0) && dbs_IsBlob(&oldData)) {
dbs_removeBlob(dbsp, &oldData);
}
if (data->size > DBS_MAX_ENTRY_SIZE) {
dbs_mkBlob(dbsp,key,data,&blob);
ret = dbs_writeBlob(dbsp, dbsp->mode, &blob, data);
data = &blob;
}
}
if (ret == 0) {
ret = (* db->put)(db, key, data, flags);
}
return(ret);
}
static int
dbs_sync(const DB *dbs, unsigned int flags)
{
DB *db = (DB *)dbs->internal;
DBS *dbsp = (DBS *)dbs;
dbs_freemap(dbsp);
return (* db->sync)(db, flags);
}
static int
dbs_del(const DB *dbs, const DBT *key, unsigned int flags)
{
int ret;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
if (!dbsp->readOnly) {
DBT oldData;
ret = (*db->get)(db,key,&oldData,0);
if ((ret == 0) && dbs_IsBlob(&oldData)) {
dbs_removeBlob(dbsp,&oldData);
}
}
return (* db->del)(db, key, flags);
}
static int
dbs_seq(const DB *dbs, DBT *key, DBT *data, unsigned int flags)
{
int ret;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
ret = (* db->seq)(db, key, data, flags);
if ((ret == 0) && dbs_IsBlob(data)) {
/* don't return a blob read as an error so traversals keep going */
(void) dbs_readBlob(dbsp,data);
}
return(ret);
}
static int
dbs_close(DB *dbs)
{
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
int ret;
dbs_freemap(dbsp);
ret = (* db->close)(db);
PORT_Free(dbsp->blobdir);
PORT_Free(dbsp);
return ret;
}
static int
dbs_fd(const DB *dbs)
{
DB *db = (DB *)dbs->internal;
return (* db->fd)(db);
}
/*
* the naming convention we use is
* change the .xxx into .dir. (for nss it's always .db);
* if no .extension exists or is equal to .dir, add a .dir
* the returned data must be freed.
*/
#define DIRSUFFIX ".dir"
static char *
dbs_mkBlobDirName(const char *dbname)
{
int dbname_len = PORT_Strlen(dbname);
int dbname_end = dbname_len;
const char *cp;
char *blobDir = NULL;
/* scan back from the end looking for either a directory separator, a '.',
* or the end of the string. NOTE: Windows should check for both separators
* here. For now this is safe because we know NSS always uses a '.'
*/
for (cp = &dbname[dbname_len];
(cp > dbname) && (*cp != '.') && (*cp != *PATH_SEPARATOR) ;
cp--)
/* Empty */ ;
if (*cp == '.') {
dbname_end = cp - dbname;
if (PORT_Strcmp(cp,DIRSUFFIX) == 0) {
dbname_end = dbname_len;
}
}
blobDir = PORT_ZAlloc(dbname_end+sizeof(DIRSUFFIX));
if (blobDir == NULL) {
return NULL;
}
PORT_Memcpy(blobDir,dbname,dbname_end);
PORT_Memcpy(&blobDir[dbname_end],DIRSUFFIX,sizeof(DIRSUFFIX));
return blobDir;
}
#define DBM_DEFAULT 0
static const HASHINFO dbs_hashInfo = {
DBS_BLOCK_SIZE, /* bucket size, must be greater than = to
* or maximum entry size (+ header)
* we allow before blobing */
DBM_DEFAULT, /* Fill Factor */
DBM_DEFAULT, /* number of elements */
DBS_CACHE_SIZE, /* cache size */
DBM_DEFAULT, /* hash function */
DBM_DEFAULT, /* byte order */
};
/*
* the open function. NOTE: this is the only exposed function in this file.
* everything else is called through the function table pointer.
*/
DB *
dbsopen(const char *dbname, int flags, int mode, DBTYPE type,
const void *userData)
{
DB *db = NULL,*dbs = NULL;
DBS *dbsp = NULL;
/* NOTE: we are overriding userData with dbs_hashInfo. since all known
* callers pass 0, this is ok, otherwise we should merge the two */
dbsp = (DBS *)PORT_ZAlloc(sizeof(DBS));
if (!dbsp) {
return NULL;
}
dbs = &dbsp->db;
dbsp->blobdir=dbs_mkBlobDirName(dbname);
if (dbsp->blobdir == NULL) {
goto loser;
}
dbsp->mode = mode;
dbsp->readOnly = (PRBool)(flags == NO_RDONLY);
dbsp->dbs_mapfile = NULL;
dbsp->dbs_addr = NULL;
dbsp->dbs_len = 0;
/* the real dbm call */
db = dbopen(dbname, flags, mode, type, &dbs_hashInfo);
if (db == NULL) {
goto loser;
}
dbs->internal = (void *) db;
dbs->type = type;
dbs->close = dbs_close;
dbs->get = dbs_get;
dbs->del = dbs_del;
dbs->put = dbs_put;
dbs->seq = dbs_seq;
dbs->sync = dbs_sync;
dbs->fd = dbs_fd;
return dbs;
loser:
if (db) {
(*db->close)(db);
}
if (dbsp) {
if (dbsp->blobdir) {
PORT_Free(dbsp->blobdir);
}
PORT_Free(dbsp);
}
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,86 +0,0 @@
/*
* private.h - Private data structures for the software token library
*
* ***** 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 ***** */
/* $Id: keydbi.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
#ifndef _KEYDBI_H_
#define _KEYDBI_H_
#include "nspr.h"
#include "seccomon.h"
#include "mcom_db.h"
/*
* Handle structure for open key databases
*/
struct NSSLOWKEYDBHandleStr {
DB *db;
DB *updatedb; /* used when updating an old version */
SECItem *global_salt; /* password hashing salt for this db */
int version; /* version of the database */
char *appname; /* multiaccess app name */
char *dbname; /* name of the openned DB */
PRBool readOnly; /* is the DB read only */
PRLock *lock;
PRInt32 ref; /* reference count */
};
/*
** Typedef for callback for traversing key database.
** "key" is the key used to index the data in the database (nickname)
** "data" is the key data
** "pdata" is the user's data
*/
typedef SECStatus (* NSSLOWKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata);
SEC_BEGIN_PROTOS
/*
** Traverse the entire key database, and pass the nicknames and keys to a
** user supplied function.
** "f" is the user function to call for each key
** "udata" is the user's data, which is passed through to "f"
*/
extern SECStatus nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
NSSLOWKEYTraverseKeysFunc f,
void *udata);
SEC_END_PROTOS
#endif /* _KEYDBI_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,955 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 ***** */
#include "secitem.h"
#include "pkcs11.h"
#include "lgdb.h"
#include "pcert.h"
#include "lowkeyi.h"
#include "blapi.h"
#include "secder.h"
#include "keydbi.h"
/*
* ******************** Object Creation Utilities ***************************
*/
/*
* check the consistancy and initialize a Certificate Object
*/
static CK_RV
lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
const CK_ATTRIBUTE *templ, CK_ULONG count)
{
SECItem derCert;
NSSLOWCERTCertificate *cert;
NSSLOWCERTCertTrust *trust = NULL;
NSSLOWCERTCertTrust userTrust =
{ CERTDB_USER, CERTDB_USER, CERTDB_USER };
NSSLOWCERTCertTrust defTrust =
{ CERTDB_TRUSTED_UNKNOWN,
CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN };
char *label = NULL;
char *email = NULL;
SECStatus rv;
PRBool inDB = PR_TRUE;
NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
NSSLOWKEYDBHandle *keyHandle = NULL;
CK_CERTIFICATE_TYPE type;
const CK_ATTRIBUTE *attribute;
/* we can't store any certs private */
if (lg_isTrue(CKA_PRIVATE, templ, count)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
/* We only support X.509 Certs for now */
attribute = lg_FindAttribute(CKA_CERTIFICATE_TYPE, templ, count);
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
type = *(CK_CERTIFICATE_TYPE *)attribute->pValue;
if (type != CKC_X_509) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
/* X.509 Certificate */
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
/* get the der cert */
attribute = lg_FindAttribute(CKA_VALUE, templ, count);
if (!attribute) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
derCert.type = 0;
derCert.data = (unsigned char *)attribute->pValue;
derCert.len = attribute->ulValueLen ;
label = lg_getString(CKA_LABEL, templ, count);
cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
if (cert == NULL) {
cert = nsslowcert_DecodeDERCertificate(&derCert, label);
inDB = PR_FALSE;
}
if (cert == NULL) {
if (label) PORT_Free(label);
return CKR_ATTRIBUTE_VALUE_INVALID;
}
keyHandle = lg_getKeyDB(sdb);
if (keyHandle) {
if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
trust = &userTrust;
}
}
if (!inDB) {
if (!trust) trust = &defTrust;
rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
} else {
rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
SECSuccess;
}
if (label) PORT_Free(label);
if (rv != SECSuccess) {
nsslowcert_DestroyCertificate(cert);
return CKR_DEVICE_ERROR;
}
/*
* Add a NULL S/MIME profile if necessary.
*/
email = lg_getString(CKA_NETSCAPE_EMAIL, templ, count);
if (email) {
certDBEntrySMime *entry;
entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
if (!entry) {
nsslowcert_SaveSMimeProfile(certHandle, email,
&cert->derSubject, NULL, NULL);
} else {
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
}
PORT_Free(email);
}
*handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT);
nsslowcert_DestroyCertificate(cert);
return CKR_OK;
}
unsigned int
lg_MapTrust(CK_TRUST trust, PRBool clientAuth)
{
unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA :
CERTDB_TRUSTED_CA;
switch (trust) {
case CKT_NETSCAPE_TRUSTED:
return CERTDB_VALID_PEER|CERTDB_TRUSTED;
case CKT_NETSCAPE_TRUSTED_DELEGATOR:
return CERTDB_VALID_CA|trustCA;
case CKT_NETSCAPE_UNTRUSTED:
return CERTDB_NOT_TRUSTED;
case CKT_NETSCAPE_MUST_VERIFY:
return 0;
case CKT_NETSCAPE_VALID: /* implies must verify */
return CERTDB_VALID_PEER;
case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */
return CERTDB_VALID_CA;
default:
break;
}
return CERTDB_TRUSTED_UNKNOWN;
}
/*
* check the consistancy and initialize a Trust Object
*/
static CK_RV
lg_createTrustObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
const CK_ATTRIBUTE *templ, CK_ULONG count)
{
const CK_ATTRIBUTE *issuer = NULL;
const CK_ATTRIBUTE *serial = NULL;
NSSLOWCERTCertificate *cert = NULL;
const CK_ATTRIBUTE *trust;
CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN;
CK_BBOOL stepUp;
NSSLOWCERTCertTrust dbTrust = { 0 };
SECStatus rv;
NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb);
NSSLOWCERTIssuerAndSN issuerSN;
/* we can't store any certs private */
if (lg_isTrue(CKA_PRIVATE, templ, count)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
issuer = lg_FindAttribute(CKA_ISSUER, templ, count);
serial = lg_FindAttribute(CKA_SERIAL_NUMBER, templ, count);
if (issuer && serial) {
issuerSN.derIssuer.data = (unsigned char *)issuer->pValue;
issuerSN.derIssuer.len = issuer->ulValueLen ;
issuerSN.serialNumber.data = (unsigned char *)serial->pValue;
issuerSN.serialNumber.len = serial->ulValueLen ;
cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
}
if (cert == NULL) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
lg_GetULongAttribute(CKA_TRUST_SERVER_AUTH, templ, count, &sslTrust);
lg_GetULongAttribute(CKA_TRUST_CLIENT_AUTH, templ, count, &clientTrust);
lg_GetULongAttribute(CKA_TRUST_EMAIL_PROTECTION, templ, count, &emailTrust);
lg_GetULongAttribute(CKA_TRUST_CODE_SIGNING, templ, count, &signTrust);
stepUp = CK_FALSE;
trust = lg_FindAttribute(CKA_TRUST_STEP_UP_APPROVED, templ, count);
if (trust) {
if (trust->ulValueLen == sizeof(CK_BBOOL)) {
stepUp = *(CK_BBOOL*)trust->pValue;
}
}
/* preserve certain old fields */
if (cert->trust) {
dbTrust.sslFlags = cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS;
dbTrust.emailFlags=
cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS;
dbTrust.objectSigningFlags =
cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS;
}
dbTrust.sslFlags |= lg_MapTrust(sslTrust,PR_FALSE);
dbTrust.sslFlags |= lg_MapTrust(clientTrust,PR_TRUE);
dbTrust.emailFlags |= lg_MapTrust(emailTrust,PR_FALSE);
dbTrust.objectSigningFlags |= lg_MapTrust(signTrust,PR_FALSE);
if (stepUp) {
dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
}
rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
*handle=lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST);
nsslowcert_DestroyCertificate(cert);
if (rv != SECSuccess) {
return CKR_DEVICE_ERROR;
}
return CKR_OK;
}
/*
* check the consistancy and initialize a Trust Object
*/
static CK_RV
lg_createSMimeObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
const CK_ATTRIBUTE *templ, CK_ULONG count)
{
SECItem derSubj,rawProfile,rawTime,emailKey;
SECItem *pRawProfile = NULL;
SECItem *pRawTime = NULL;
char *email = NULL;
const CK_ATTRIBUTE *subject = NULL,
*profile = NULL,
*time = NULL;
SECStatus rv;
NSSLOWCERTCertDBHandle *certHandle;
CK_RV ck_rv = CKR_OK;
/* we can't store any certs private */
if (lg_isTrue(CKA_PRIVATE,templ,count)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
certHandle = lg_getCertDB(sdb);
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
/* lookup SUBJECT */
subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
PORT_Assert(subject);
if (!subject) {
ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto loser;
}
derSubj.data = (unsigned char *)subject->pValue;
derSubj.len = subject->ulValueLen ;
derSubj.type = 0;
/* lookup VALUE */
profile = lg_FindAttribute(CKA_VALUE,templ,count);
if (profile) {
rawProfile.data = (unsigned char *)profile->pValue;
rawProfile.len = profile->ulValueLen ;
rawProfile.type = siBuffer;
pRawProfile = &rawProfile;
}
/* lookup Time */
time = lg_FindAttribute(CKA_NETSCAPE_SMIME_TIMESTAMP,templ,count);
if (time) {
rawTime.data = (unsigned char *)time->pValue;
rawTime.len = time->ulValueLen ;
rawTime.type = siBuffer;
pRawTime = &rawTime;
}
email = lg_getString(CKA_NETSCAPE_EMAIL,templ,count);
if (!email) {
ck_rv = CKR_ATTRIBUTE_VALUE_INVALID;
goto loser;
}
/* Store S/MIME Profile by SUBJECT */
rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
pRawProfile,pRawTime);
if (rv != SECSuccess) {
ck_rv = CKR_DEVICE_ERROR;
goto loser;
}
emailKey.data = (unsigned char *)email;
emailKey.len = PORT_Strlen(email)+1;
*handle = lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME);
loser:
if (email) PORT_Free(email);
return ck_rv;
}
/*
* check the consistancy and initialize a Trust Object
*/
static CK_RV
lg_createCrlObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
const CK_ATTRIBUTE *templ, CK_ULONG count)
{
PRBool isKRL = PR_FALSE;
SECItem derSubj,derCrl;
char *url = NULL;
const CK_ATTRIBUTE *subject,*crl;
SECStatus rv;
NSSLOWCERTCertDBHandle *certHandle;
certHandle = lg_getCertDB(sdb);
/* we can't store any private crls */
if (lg_isTrue(CKA_PRIVATE,templ,count)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
/* lookup SUBJECT */
subject = lg_FindAttribute(CKA_SUBJECT,templ,count);
if (!subject) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
derSubj.data = (unsigned char *)subject->pValue;
derSubj.len = subject->ulValueLen ;
/* lookup VALUE */
crl = lg_FindAttribute(CKA_VALUE,templ,count);
PORT_Assert(crl);
if (!crl) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
derCrl.data = (unsigned char *)crl->pValue;
derCrl.len = crl->ulValueLen ;
url = lg_getString(CKA_NETSCAPE_URL,templ,count);
isKRL = lg_isTrue(CKA_NETSCAPE_KRL,templ,count);
/* Store CRL by SUBJECT */
rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
if (url) {
PORT_Free(url);
}
if (rv != SECSuccess) {
return CKR_DEVICE_ERROR;
}
/* if we overwrote the existing CRL, poison the handle entry so we get
* a new object handle */
(void) lg_poisonHandle(sdb, &derSubj,
isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
*handle = lg_mkHandle(sdb, &derSubj,
isKRL ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL);
return CKR_OK;
}
/*
* check the consistancy and initialize a Public Key Object
*/
static CK_RV
lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE;
CK_RV crv;
NSSLOWKEYPrivateKey *priv;
SECItem pubKey;
NSSLOWKEYDBHandle *keyHandle = NULL;
switch (key_type) {
case CKK_RSA:
pubKeyAttr = CKA_MODULUS;
break;
#ifdef NSS_ENABLE_ECC
case CKK_EC:
pubKeyAttr = CKA_EC_POINT;
break;
#endif /* NSS_ENABLE_ECC */
case CKK_DSA:
case CKK_DH:
break;
default:
return CKR_ATTRIBUTE_VALUE_INVALID;
}
crv = lg_Attribute2SSecItem(NULL,pubKeyAttr,templ,count,&pubKey);
if (crv != CKR_OK) return crv;
PORT_Assert(pubKey.data);
keyHandle = lg_getKeyDB(sdb);
if (keyHandle == NULL) {
PORT_Free(pubKey.data);
return CKR_TOKEN_WRITE_PROTECTED;
}
if (keyHandle->version != 3) {
unsigned char buf[SHA1_LENGTH];
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
pubKey.len = sizeof(buf);
}
/* make sure the associated private key already exists */
/* only works if we are logged in */
priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, sdb /*password*/);
if (priv == NULL) {
PORT_Free(pubKey.data);
return crv;
}
nsslowkey_DestroyPrivateKey(priv);
*handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_PUB);
PORT_Free(pubKey.data);
return CKR_OK;
}
/* make a private key from a verified object */
static NSSLOWKEYPrivateKey *
lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
CK_KEY_TYPE key_type, CK_RV *crvp)
{
NSSLOWKEYPrivateKey *privKey;
PLArenaPool *arena;
CK_RV crv = CKR_OK;
SECStatus rv;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
*crvp = CKR_HOST_MEMORY;
return NULL;
}
privKey = (NSSLOWKEYPrivateKey *)
PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
if (privKey == NULL) {
PORT_FreeArena(arena,PR_FALSE);
*crvp = CKR_HOST_MEMORY;
return NULL;
}
/* in future this would be a switch on key_type */
privKey->arena = arena;
switch (key_type) {
case CKK_RSA:
privKey->keyType = NSSLOWKEYRSAKey;
crv=lg_Attribute2SSecItem(arena,CKA_MODULUS,templ,count,
&privKey->u.rsa.modulus);
if (crv != CKR_OK) break;
crv=lg_Attribute2SSecItem(arena,CKA_PUBLIC_EXPONENT,templ,count,
&privKey->u.rsa.publicExponent);
if (crv != CKR_OK) break;
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIVATE_EXPONENT,templ,count,
&privKey->u.rsa.privateExponent, sdb);
if (crv != CKR_OK) break;
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_1,templ,count,
&privKey->u.rsa.prime1, sdb);
if (crv != CKR_OK) break;
crv=lg_PrivAttr2SSecItem(arena,CKA_PRIME_2,templ,count,
&privKey->u.rsa.prime2, sdb);
if (crv != CKR_OK) break;
crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_1,templ,count,
&privKey->u.rsa.exponent1, sdb);
if (crv != CKR_OK) break;
crv=lg_PrivAttr2SSecItem(arena,CKA_EXPONENT_2,templ,count,
&privKey->u.rsa.exponent2, sdb);
if (crv != CKR_OK) break;
crv=lg_PrivAttr2SSecItem(arena,CKA_COEFFICIENT,templ,count,
&privKey->u.rsa.coefficient, sdb);
if (crv != CKR_OK) break;
rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
NSSLOWKEY_VERSION);
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
break;
case CKK_DSA:
privKey->keyType = NSSLOWKEYDSAKey;
crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
&privKey->u.dsa.params.prime);
if (crv != CKR_OK) break;
crv = lg_Attribute2SSecItem(arena,CKA_SUBPRIME,templ,count,
&privKey->u.dsa.params.subPrime);
if (crv != CKR_OK) break;
crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
&privKey->u.dsa.params.base);
if (crv != CKR_OK) break;
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
&privKey->u.dsa.privateValue, sdb);
if (crv != CKR_OK) break;
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ,count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
&privKey->u.dsa.publicValue);
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
}
break;
case CKK_DH:
privKey->keyType = NSSLOWKEYDHKey;
crv = lg_Attribute2SSecItem(arena,CKA_PRIME,templ,count,
&privKey->u.dh.prime);
if (crv != CKR_OK) break;
crv = lg_Attribute2SSecItem(arena,CKA_BASE,templ,count,
&privKey->u.dh.base);
if (crv != CKR_OK) break;
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
&privKey->u.dh.privateValue, sdb);
if (crv != CKR_OK) break;
if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
&privKey->u.dh.publicValue);
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
}
break;
#ifdef NSS_ENABLE_ECC
case CKK_EC:
privKey->keyType = NSSLOWKEYECKey;
crv = lg_Attribute2SSecItem(arena, CKA_EC_PARAMS,templ,count,
&privKey->u.ec.ecParams.DEREncoding);
if (crv != CKR_OK) break;
/* Fill out the rest of the ecParams structure
* based on the encoded params
*/
if (LGEC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
&privKey->u.ec.ecParams) != SECSuccess) {
crv = CKR_DOMAIN_PARAMS_INVALID;
break;
}
crv = lg_PrivAttr2SSecItem(arena,CKA_VALUE,templ,count,
&privKey->u.ec.privateValue, sdb);
if (crv != CKR_OK) break;
if (lg_hasAttribute(CKA_NETSCAPE_DB,templ,count)) {
crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB,templ,count,
&privKey->u.ec.publicValue);
if (crv != CKR_OK) break;
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
}
rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
break;
#endif /* NSS_ENABLE_ECC */
default:
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
}
*crvp = crv;
if (crv != CKR_OK) {
PORT_FreeArena(arena,PR_FALSE);
return NULL;
}
return privKey;
}
/*
* check the consistancy and initialize a Private Key Object
*/
static CK_RV
lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
NSSLOWKEYPrivateKey *privKey;
char *label;
SECStatus rv = SECSuccess;
CK_RV crv = CKR_DEVICE_ERROR;
SECItem pubKey;
NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb);
if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
privKey=lg_mkPrivKey(sdb, templ,count,key_type,&crv);
if (privKey == NULL) return crv;
label = lg_getString(CKA_LABEL,templ,count);
crv = lg_Attribute2SSecItem(NULL,CKA_NETSCAPE_DB,templ,count,&pubKey);
if (crv != CKR_OK) {
crv = CKR_TEMPLATE_INCOMPLETE;
rv = SECFailure;
goto fail;
}
#ifdef notdef
if (keyHandle->version != 3) {
unsigned char buf[SHA1_LENGTH];
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
pubKey.len = sizeof(buf);
}
#endif
/* get the key type */
if (key_type == CKK_RSA) {
rv = RSA_PrivateKeyCheck(&privKey->u.rsa);
if (rv == SECFailure) {
goto fail;
}
}
rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
label, sdb /*->password*/);
fail:
if (label) PORT_Free(label);
*handle = lg_mkHandle(sdb,&pubKey,LG_TOKEN_TYPE_PRIV);
if (pubKey.data) PORT_Free(pubKey.data);
nsslowkey_DestroyPrivateKey(privKey);
if (rv != SECSuccess) return crv;
return CKR_OK;
}
#define LG_KEY_MAX_RETRIES 10 /* don't hang if we are having problems with the rng */
#define LG_KEY_ID_SIZE 18 /* don't use either SHA1 or MD5 sizes */
/*
* Secret keys must have a CKA_ID value to be stored in the database. This code
* will generate one if there wasn't one already.
*/
static CK_RV
lg_GenerateSecretCKA_ID(NSSLOWKEYDBHandle *handle, SECItem *id, char *label)
{
unsigned int retries;
SECStatus rv = SECSuccess;
CK_RV crv = CKR_OK;
id->data = NULL;
if (label) {
id->data = (unsigned char *)PORT_Strdup(label);
if (id->data == NULL) {
return CKR_HOST_MEMORY;
}
id->len = PORT_Strlen(label)+1;
if (!nsslowkey_KeyForIDExists(handle,id)) {
return CKR_OK;
}
PORT_Free(id->data);
id->data = NULL;
id->len = 0;
}
id->data = (unsigned char *)PORT_Alloc(LG_KEY_ID_SIZE);
if (id->data == NULL) {
return CKR_HOST_MEMORY;
}
id->len = LG_KEY_ID_SIZE;
retries = 0;
do {
rv = RNG_GenerateGlobalRandomBytes(id->data,id->len);
} while (rv == SECSuccess && nsslowkey_KeyForIDExists(handle,id) &&
(++retries <= LG_KEY_MAX_RETRIES));
if ((rv != SECSuccess) || (retries > LG_KEY_MAX_RETRIES)) {
crv = CKR_DEVICE_ERROR; /* random number generator is bad */
PORT_Free(id->data);
id->data = NULL;
id->len = 0;
}
return crv;
}
static NSSLOWKEYPrivateKey *lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ,
CK_ULONG count, CK_KEY_TYPE key_type,
SECItem *pubkey, SDB *sdbpw)
{
NSSLOWKEYPrivateKey *privKey = 0;
PLArenaPool *arena = 0;
CK_KEY_TYPE keyType;
PRUint32 keyTypeStorage;
SECItem keyTypeItem;
CK_RV crv;
SECStatus rv;
static unsigned char derZero[1] = { 0 };
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
privKey = (NSSLOWKEYPrivateKey *)
PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey));
if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
privKey->arena = arena;
/* Secret keys are represented in the database as "fake" RSA keys.
* The RSA key is marked as a secret key representation by setting the
* public exponent field to 0, which is an invalid RSA exponent.
* The other fields are set as follows:
* modulus - CKA_ID value for the secret key
* private exponent - CKA_VALUE (the key itself)
* coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
* is used for the key.
* all others - set to integer 0
*/
privKey->keyType = NSSLOWKEYRSAKey;
/* The modulus is set to the key id of the symmetric key */
crv = lg_Attribute2SecItem(arena, CKA_ID, templ, count,
&privKey->u.rsa.modulus);
if (crv != CKR_OK) goto loser;
/* The public exponent is set to 0 length to indicate a special key */
privKey->u.rsa.publicExponent.len = sizeof derZero;
privKey->u.rsa.publicExponent.data = derZero;
/* The private exponent is the actual key value */
crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count,
&privKey->u.rsa.privateExponent, sdbpw);
if (crv != CKR_OK) goto loser;
/* All other fields empty - needs testing */
privKey->u.rsa.prime1.len = sizeof derZero;
privKey->u.rsa.prime1.data = derZero;
privKey->u.rsa.prime2.len = sizeof derZero;
privKey->u.rsa.prime2.data = derZero;
privKey->u.rsa.exponent1.len = sizeof derZero;
privKey->u.rsa.exponent1.data = derZero;
privKey->u.rsa.exponent2.len = sizeof derZero;
privKey->u.rsa.exponent2.data = derZero;
/* Coeficient set to KEY_TYPE */
crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType);
if (crv != CKR_OK) goto loser;
/* on 64 bit platforms, we still want to store 32 bits of keyType (This is
* safe since the PKCS #11 defines for all types are 32 bits or less). */
keyTypeStorage = (PRUint32) keyType;
keyTypeStorage = PR_htonl(keyTypeStorage);
keyTypeItem.data = (unsigned char *)&keyTypeStorage;
keyTypeItem.len = sizeof (keyTypeStorage);
rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem);
if (rv != SECSuccess) {
crv = CKR_HOST_MEMORY;
goto loser;
}
/* Private key version field set normally for compatibility */
rv = DER_SetUInteger(privKey->arena,
&privKey->u.rsa.version, NSSLOWKEY_VERSION);
if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
loser:
if (crv != CKR_OK) {
PORT_FreeArena(arena,PR_FALSE);
privKey = 0;
}
return privKey;
}
/*
* check the consistancy and initialize a Secret Key Object
*/
static CK_RV
lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
CK_RV crv;
NSSLOWKEYPrivateKey *privKey = NULL;
NSSLOWKEYDBHandle *keyHandle = NULL;
SECItem pubKey;
char *label = NULL;
SECStatus rv = SECSuccess;
pubKey.data = 0;
/* If the object is a TOKEN object, store in the database */
keyHandle = lg_getKeyDB(sdb);
if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
label = lg_getString(CKA_LABEL,templ,count);
crv = lg_Attribute2SecItem(NULL,CKA_ID,templ,count,&pubKey);
/* Should this be ID? */
if (crv != CKR_OK) goto loser;
/* if we don't have an ID, generate one */
if (pubKey.len == 0) {
if (pubKey.data) {
PORT_Free(pubKey.data);
pubKey.data = NULL;
}
crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
if (crv != CKR_OK) goto loser;
}
privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb);
if (privKey == NULL) {
crv = CKR_HOST_MEMORY;
goto loser;
}
rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
privKey, &pubKey, label, sdb /*->password*/);
if (rv != SECSuccess) {
crv = CKR_DEVICE_ERROR;
goto loser;
}
*handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY);
loser:
if (label) PORT_Free(label);
if (privKey) nsslowkey_DestroyPrivateKey(privKey);
if (pubKey.data) PORT_Free(pubKey.data);
return crv;
}
/*
* check the consistancy and initialize a Key Object
*/
static CK_RV
lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
CK_RV crv;
CK_KEY_TYPE key_type;
/* get the key type */
crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &key_type);
if (crv != CKR_OK) {
return crv;
}
switch (objclass) {
case CKO_PUBLIC_KEY:
return lg_createPublicKeyObject(sdb,key_type,handle,templ,count);
case CKO_PRIVATE_KEY:
return lg_createPrivateKeyObject(sdb,key_type,handle,templ,count);
case CKO_SECRET_KEY:
return lg_createSecretKeyObject(sdb,key_type,handle,templ,count);
default:
break;
}
return CKR_ATTRIBUTE_VALUE_INVALID;
}
/*
* Parse the template and create an object stored in the DB that reflects.
* the object specified in the database.
*/
CK_RV
lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
const CK_ATTRIBUTE *templ, CK_ULONG count)
{
CK_RV crv;
CK_OBJECT_CLASS objclass;
/* get the object class */
crv = lg_GetULongAttribute(CKA_CLASS, templ, count, &objclass);
if (crv != CKR_OK) {
return crv;
}
/* Now handle the specific object class.
*/
switch (objclass) {
case CKO_CERTIFICATE:
crv = lg_createCertObject(sdb,handle,templ,count);
break;
case CKO_NETSCAPE_TRUST:
crv = lg_createTrustObject(sdb,handle,templ,count);
break;
case CKO_NETSCAPE_CRL:
crv = lg_createCrlObject(sdb,handle,templ,count);
break;
case CKO_NETSCAPE_SMIME:
crv = lg_createSMimeObject(sdb,handle,templ,count);
break;
case CKO_PRIVATE_KEY:
case CKO_PUBLIC_KEY:
case CKO_SECRET_KEY:
crv = lg_createKeyObject(sdb,objclass,handle,templ,count);
break;
default:
crv = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
return crv;
}

View File

@@ -1,197 +0,0 @@
/* ***** 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 ***** */
/*
* Internal data structures and functions used by pkcs11.c
*/
#ifndef _LGDB_H_
#define _LGDB_H_ 1
#include "nssilock.h"
#include "seccomon.h"
#include "secoidt.h"
#include "lowkeyti.h"
#include "pkcs11t.h"
#include "sdb.h"
#include "cdbhdl.h"
#define MULTIACCESS "multiaccess:"
/* machine dependent path stuff used by dbinit.c and pk11db.c */
#ifdef macintosh
#define PATH_SEPARATOR ":"
#define SECMOD_DB "Security Modules"
#define CERT_DB_FMT "%sCertificates%s"
#define KEY_DB_FMT "%sKey Database%s"
#else
#define PATH_SEPARATOR "/"
#define SECMOD_DB "secmod.db"
#define CERT_DB_FMT "%scert%s.db"
#define KEY_DB_FMT "%skey%s.db"
#endif
SEC_BEGIN_PROTOS
/* internal utility functions used by pkcs11.c */
extern const CK_ATTRIBUTE *lg_FindAttribute(CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count);
extern CK_RV lg_Attribute2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item);
extern CK_RV lg_Attribute2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item);
extern CK_RV lg_PrivAttr2SecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item, SDB *sdbpw);
extern CK_RV lg_PrivAttr2SSecItem(PLArenaPool *,CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item, SDB *sdbpw);
extern CK_RV lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
CK_ULONG *out);
extern PRBool lg_hasAttribute(CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count);
extern PRBool lg_isTrue(CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count);
extern PRBool lg_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass);
extern char *lg_getString(CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count);
extern unsigned int lg_MapTrust(CK_TRUST trust, PRBool clientAuth);
/* clear out all the existing object ID to database key mappings.
* used to reinit a token */
extern CK_RV SFTK_ClearTokenKeyHashTable(SDB *sdb);
extern void lg_FreeSearch(SDBFind *search);
NSSLOWCERTCertDBHandle *lg_getCertDB(SDB *sdb);
NSSLOWKEYDBHandle *lg_getKeyDB(SDB *sdb);
const char *lg_EvaluateConfigDir(const char *configdir, char **domain);
/*
* object handle modifiers
*/
#define LG_TOKEN_MASK 0xc0000000L
#define LG_TOKEN_TYPE_MASK 0x38000000L
#define LG_TOKEN_TYPE_SHIFT 27
/* keydb (high bit == 0) */
#define LG_TOKEN_TYPE_PRIV 0x08000000L
#define LG_TOKEN_TYPE_PUB 0x10000000L
#define LG_TOKEN_TYPE_KEY 0x18000000L
/* certdb (high bit == 1) */
#define LG_TOKEN_TYPE_TRUST 0x20000000L
#define LG_TOKEN_TYPE_CRL 0x28000000L
#define LG_TOKEN_TYPE_SMIME 0x30000000L
#define LG_TOKEN_TYPE_CERT 0x38000000L
#define LG_TOKEN_KRL_HANDLE (LG_TOKEN_TYPE_CRL|1)
#define LG_SEARCH_BLOCK_SIZE 10
#define LG_BUF_SPACE 50
#define LG_STRICT PR_FALSE
/*
* token object utilities
*/
void lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle);
PRBool lg_poisonHandle(SDB *sdb, SECItem *dbkey, CK_OBJECT_HANDLE handle);
PRBool lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
const CK_ATTRIBUTE *templ, CK_ULONG count);
const SECItem *lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
CK_OBJECT_HANDLE lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class);
SECStatus lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle);
SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdbpw,
SECItem *plainText, SECItem **cipherText);
SECStatus lg_util_decrypt(SDB *sdbpw,
SECItem *cipherText, SECItem **plainText);
PLHashTable *lg_GetHashTable(SDB *sdb);
void lg_DBLock(SDB *sdb);
void lg_DBUnlock(SDB *sdb);
typedef void (*LGFreeFunc)(void *);
/*
* database functions
*/
/* lg_FindObjectsInit initializes a search for token and session objects
* that match a template. */
CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
CK_ULONG ulCount, SDBFind **search);
/* lg_FindObjects continues a search for token and session objects
* that match a template, obtaining additional object handles. */
CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
CK_ULONG *pulObjectCount);
/* lg_FindObjectsFinal finishes a search for token and session objects. */
CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search);
/* lg_CreateObject parses the template and create an object stored in the
* DB that reflects the object specified in the template. */
CK_RV lg_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *handle,
const CK_ATTRIBUTE *templ, CK_ULONG count);
CK_RV lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count);
CK_RV lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
const CK_ATTRIBUTE *template, CK_ULONG count);
CK_RV lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id);
CK_RV lg_Close(SDB *sdb);
CK_RV lg_Reset(SDB *sdb);
/*
* The old database doesn't share and doesn't support
* transactions.
*/
CK_RV lg_Begin(SDB *sdb);
CK_RV lg_Commit(SDB *sdb);
CK_RV lg_Abort(SDB *sdb);
CK_RV lg_GetPWEntry(SDB *sdb, SDBPasswordEntry *entry);
CK_RV lg_PutPWEntry(SDB *sdb, SDBPasswordEntry *entry);
SEC_END_PROTOS
#endif /* _LGDB_H_ */

View File

@@ -1,64 +0,0 @@
;+#
;+# ***** 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) 2000
;+# the Initial Developer. All Rights Reserved.
;+#
;+# Contributor(s):
;+# Dr Stephen Henson <stephen.henson@gemplus.com>
;+#
;+# 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 *****
;+#
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
;+# 1. For all unix platforms, the string ";-" means "remove this line"
;+# 2. For all unix platforms, the string " DATA " will be removed from any
;+# line on which it occurs.
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
;+# On AIX, lines containing ";+" will be removed.
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
;+# 5. For all unix platforms, after the above processing has taken place,
;+# all characters after the first ";" on the line will be removed.
;+# And for AIX, the first ";" will also be removed.
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
;+# directives are hidden behind ";", ";+", and ";-"
;+LGDBM_3.12 { # NSS 3.12 release
;+ global:
LIBRARY lgdbm3 ;-
EXPORTS ;-
legacy_Open;
legacy_Shutdown;
legacy_ReadSecmodDB;
legacy_ReleaseSecmodDBData;
legacy_AddSecmodDB;
legacy_DeleteSecmodDB;
legacy_SetCryptFunctions;
;+ local:
;+ *;
;+};

View File

@@ -1,144 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 ***** */
/*
* Internal PKCS #11 functions. Should only be called by pkcs11.c
*/
#include "pkcs11.h"
#include "lgdb.h"
#include "pcert.h"
#include "lowkeyi.h"
/*
* remove an object.
*/
CK_RV
lg_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
{
CK_RV crv = CKR_OK;
SECStatus rv;
NSSLOWCERTCertificate *cert;
NSSLOWCERTCertTrust tmptrust;
PRBool isKrl;
NSSLOWKEYDBHandle *keyHandle;
NSSLOWCERTCertDBHandle *certHandle;
const SECItem *dbKey;
object_id &= ~LG_TOKEN_MASK;
dbKey = lg_lookupTokenKeyByHandle(sdb,object_id);
if (dbKey == NULL) {
return CKR_OBJECT_HANDLE_INVALID;
}
/* remove the objects from the real data base */
switch (object_id & LG_TOKEN_TYPE_MASK) {
case LG_TOKEN_TYPE_PRIV:
case LG_TOKEN_TYPE_KEY:
/* KEYID is the public KEY for DSA and DH, and the MODULUS for
* RSA */
keyHandle = lg_getKeyDB(sdb);
if (!keyHandle) {
crv = CKR_TOKEN_WRITE_PROTECTED;
break;
}
rv = nsslowkey_DeleteKey(keyHandle, dbKey);
if (rv != SECSuccess) {
crv = CKR_DEVICE_ERROR;
}
break;
case LG_TOKEN_TYPE_PUB:
break; /* public keys only exist at the behest of the priv key */
case LG_TOKEN_TYPE_CERT:
certHandle = lg_getCertDB(sdb);
if (!certHandle) {
crv = CKR_TOKEN_WRITE_PROTECTED;
break;
}
cert = nsslowcert_FindCertByKey(certHandle,dbKey);
if (cert == NULL) {
crv = CKR_DEVICE_ERROR;
break;
}
rv = nsslowcert_DeletePermCertificate(cert);
if (rv != SECSuccess) {
crv = CKR_DEVICE_ERROR;
}
nsslowcert_DestroyCertificate(cert);
break;
case LG_TOKEN_TYPE_CRL:
certHandle = lg_getCertDB(sdb);
if (!certHandle) {
crv = CKR_TOKEN_WRITE_PROTECTED;
break;
}
isKrl = (PRBool) (object_id == LG_TOKEN_KRL_HANDLE);
rv = nsslowcert_DeletePermCRL(certHandle, dbKey, isKrl);
if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
break;
case LG_TOKEN_TYPE_TRUST:
certHandle = lg_getCertDB(sdb);
if (!certHandle) {
crv = CKR_TOKEN_WRITE_PROTECTED;
break;
}
cert = nsslowcert_FindCertByKey(certHandle, dbKey);
if (cert == NULL) {
crv = CKR_DEVICE_ERROR;
break;
}
tmptrust = *cert->trust;
tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
nsslowcert_DestroyCertificate(cert);
break;
default:
break;
}
lg_DBLock(sdb);
lg_deleteTokenKeyByHandle(sdb,object_id);
lg_DBUnlock(sdb);
return crv;
}

View File

@@ -1,941 +0,0 @@
/* ***** 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.
*
*
* 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 ***** */
#include "secitem.h"
#include "pkcs11.h"
#include "lgdb.h"
#include "lowkeyi.h"
#include "pcert.h"
#include "blapi.h"
#include "keydbi.h"
/*
* This code maps PKCS #11 Finds to legacy database searches. This code
* was orginally in pkcs11.c in previous versions of NSS.
*/
struct SDBFindStr {
CK_OBJECT_HANDLE *handles;
int size;
int index;
int array_size;
};
/*
* free a search structure
*/
void
lg_FreeSearch(SDBFind *search)
{
if (search->handles) {
PORT_Free(search->handles);
}
PORT_Free(search);
}
void
lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
{
if (search->handles == NULL) {
return;
}
if (search->size >= search->array_size) {
search->array_size += LG_SEARCH_BLOCK_SIZE;
search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
sizeof(CK_OBJECT_HANDLE)* search->array_size);
if (search->handles == NULL) {
return;
}
}
search->handles[search->size] = handle;
search->size++;
}
/*
* find any certs that may match the template and load them.
*/
#define LG_CERT 0x00000001
#define LG_TRUST 0x00000002
#define LG_CRL 0x00000004
#define LG_SMIME 0x00000008
#define LG_PRIVATE 0x00000010
#define LG_PUBLIC 0x00000020
#define LG_KEY 0x00000040
/*
* structure to collect key handles.
*/
typedef struct lgEntryDataStr {
SDB *sdb;
SDBFind *searchHandles;
const CK_ATTRIBUTE *template;
CK_ULONG templ_count;
} lgEntryData;
static SECStatus
lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
{
lgEntryData *crlData;
CK_OBJECT_HANDLE class_handle;
SDB *sdb;
crlData = (lgEntryData *)arg;
sdb = crlData->sdb;
class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
LG_TOKEN_KRL_HANDLE;
if (lg_tokenMatch(sdb, key, class_handle,
crlData->template, crlData->templ_count)) {
lg_addHandle(crlData->searchHandles,
lg_mkHandle(sdb,key,class_handle));
}
return(SECSuccess);
}
static void
lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl,
unsigned long classFlags, SDBFind *search,
const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
{
NSSLOWCERTCertDBHandle *certHandle = NULL;
certHandle = lg_getCertDB(sdb);
if (certHandle == NULL) {
return;
}
if (derSubject->data != NULL) {
certDBEntryRevocation *crl =
nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
if (crl != NULL) {
lg_addHandle(search, lg_mkHandle(sdb, derSubject,
isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL));
nsslowcert_DestroyDBEntry((certDBEntry *)crl);
}
} else {
lgEntryData crlData;
/* traverse */
crlData.sdb = sdb;
crlData.searchHandles = search;
crlData.template = pTemplate;
crlData.templ_count = ulCount;
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
lg_crl_collect, (void *)&crlData);
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
lg_crl_collect, (void *)&crlData);
}
}
/*
* structure to collect key handles.
*/
typedef struct lgKeyDataStr {
SDB *sdb;
NSSLOWKEYDBHandle *keyHandle;
SDBFind *searchHandles;
SECItem *id;
const CK_ATTRIBUTE *template;
CK_ULONG templ_count;
unsigned long classFlags;
PRBool strict;
} lgKeyData;
static PRBool
isSecretKey(NSSLOWKEYPrivateKey *privKey)
{
if (privKey->keyType == NSSLOWKEYRSAKey &&
privKey->u.rsa.publicExponent.len == 1 &&
privKey->u.rsa.publicExponent.data[0] == 0)
return PR_TRUE;
return PR_FALSE;
}
static SECStatus
lg_key_collect(DBT *key, DBT *data, void *arg)
{
lgKeyData *keyData;
NSSLOWKEYPrivateKey *privKey = NULL;
SECItem tmpDBKey;
SDB *sdb;
unsigned long classFlags;
keyData = (lgKeyData *)arg;
sdb = keyData->sdb;
classFlags = keyData->classFlags;
tmpDBKey.data = key->data;
tmpDBKey.len = key->size;
tmpDBKey.type = siBuffer;
PORT_Assert(keyData->keyHandle);
if (!keyData->strict && keyData->id) {
SECItem result;
PRBool haveMatch= PR_FALSE;
unsigned char hashKey[SHA1_LENGTH];
result.data = hashKey;
result.len = sizeof(hashKey);
if (keyData->id->len == 0) {
/* Make sure this isn't a LG_KEY */
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
&tmpDBKey, keyData->sdb/*->password*/);
if (privKey) {
/* turn off the unneeded class flags */
classFlags &= isSecretKey(privKey) ? ~(LG_PRIVATE|LG_PUBLIC) :
~LG_KEY;
haveMatch = (PRBool)
((classFlags & (LG_KEY|LG_PRIVATE|LG_PUBLIC)) != 0);
nsslowkey_DestroyPrivateKey(privKey);
}
} else {
SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
/* This is a fix for backwards compatibility. The key
* database indexes private keys by the public key, and
* versions of NSS prior to 3.4 stored the public key as
* a signed integer. The public key is now treated as an
* unsigned integer, with no leading zero. In order to
* correctly compute the hash of an old key, it is necessary
* to fallback and detect the leading zero.
*/
SHA1_HashBuf(hashKey,
(unsigned char *)key->data + 1, key->size - 1);
haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
}
}
if (haveMatch) {
if (classFlags & LG_PRIVATE) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
}
if (classFlags & LG_PUBLIC) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
}
if (classFlags & LG_KEY) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
}
}
return SECSuccess;
}
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey,
keyData->sdb/*->password*/);
if ( privKey == NULL ) {
goto loser;
}
if (isSecretKey(privKey)) {
if ((classFlags & LG_KEY) &&
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
keyData->template, keyData->templ_count)) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
}
} else {
if ((classFlags & LG_PRIVATE) &&
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
keyData->template, keyData->templ_count)) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
}
if ((classFlags & LG_PUBLIC) &&
lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
keyData->template, keyData->templ_count)) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(keyData->sdb, &tmpDBKey,LG_TOKEN_TYPE_PUB));
}
}
loser:
if ( privKey ) {
nsslowkey_DestroyPrivateKey(privKey);
}
return(SECSuccess);
}
static void
lg_searchKeys(SDB *sdb, SECItem *key_id,
unsigned long classFlags, SDBFind *search, PRBool mustStrict,
const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
{
NSSLOWKEYDBHandle *keyHandle = NULL;
NSSLOWKEYPrivateKey *privKey;
lgKeyData keyData;
PRBool found = PR_FALSE;
keyHandle = lg_getKeyDB(sdb);
if (keyHandle == NULL) {
return;
}
if (key_id->data) {
privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb);
if (privKey) {
if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
lg_addHandle(search,
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_KEY));
found = PR_TRUE;
}
if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
lg_addHandle(search,
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PRIV));
found = PR_TRUE;
}
if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
lg_addHandle(search,
lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PUB));
found = PR_TRUE;
}
nsslowkey_DestroyPrivateKey(privKey);
}
/* don't do the traversal if we have an up to date db */
if (keyHandle->version != 3) {
goto loser;
}
/* don't do the traversal if it can't possibly be the correct id */
/* all soft token id's are SHA1_HASH_LEN's */
if (key_id->len != SHA1_LENGTH) {
goto loser;
}
if (found) {
/* if we already found some keys, don't do the traversal */
goto loser;
}
}
keyData.sdb = sdb;
keyData.keyHandle = keyHandle;
keyData.searchHandles = search;
keyData.id = key_id;
keyData.template = pTemplate;
keyData.templ_count = ulCount;
keyData.classFlags = classFlags;
keyData.strict = mustStrict ? mustStrict : LG_STRICT;
nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData);
loser:
return;
}
/*
* structure to collect certs into
*/
typedef struct lgCertDataStr {
SDB *sdb;
int cert_count;
int max_cert_count;
NSSLOWCERTCertificate **certs;
const CK_ATTRIBUTE *template;
CK_ULONG templ_count;
unsigned long classFlags;
PRBool strict;
} lgCertData;
/*
* collect all the certs from the traverse call.
*/
static SECStatus
lg_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
{
lgCertData *cd = (lgCertData *)arg;
if (cert == NULL) {
return SECSuccess;
}
if (cd->certs == NULL) {
return SECFailure;
}
if (cd->strict) {
if ((cd->classFlags & LG_CERT) && !lg_tokenMatch(cd->sdb,
&cert->certKey, LG_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
return SECSuccess;
}
if ((cd->classFlags & LG_TRUST) && !lg_tokenMatch(cd->sdb,
&cert->certKey, LG_TOKEN_TYPE_TRUST,
cd->template, cd->templ_count)) {
return SECSuccess;
}
}
/* allocate more space if we need it. This should only happen in
* the general traversal case */
if (cd->cert_count >= cd->max_cert_count) {
int size;
cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
if (cd->certs == NULL) {
return SECFailure;
}
}
cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
return SECSuccess;
}
/* provide impedence matching ... */
static SECStatus
lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
{
return lg_cert_collect(cert, arg);
}
static void
lg_searchSingleCert(lgCertData *certData,NSSLOWCERTCertificate *cert)
{
if (cert == NULL) {
return;
}
if (certData->strict &&
!lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT,
certData->template,certData->templ_count)) {
nsslowcert_DestroyCertificate(cert);
return;
}
certData->certs = (NSSLOWCERTCertificate **)
PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
if (certData->certs == NULL) {
nsslowcert_DestroyCertificate(cert);
return;
}
certData->certs[0] = cert;
certData->cert_count = 1;
}
static void
lg_CertSetupData(lgCertData *certData,int count)
{
certData->max_cert_count = count;
if (certData->max_cert_count <= 0) {
return;
}
certData->certs = (NSSLOWCERTCertificate **)
PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
return;
}
static void
lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name,
SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN,
SECItem *email,
unsigned long classFlags, SDBFind *handles,
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
{
NSSLOWCERTCertDBHandle *certHandle = NULL;
lgCertData certData;
int i;
certHandle = lg_getCertDB(sdb);
if (certHandle == NULL) return;
certData.sdb = sdb;
certData.max_cert_count = 0;
certData.certs = NULL;
certData.cert_count = 0;
certData.template = pTemplate;
certData.templ_count = ulCount;
certData.classFlags = classFlags;
certData.strict = LG_STRICT;
/*
* Find the Cert.
*/
if (derCert->data != NULL) {
NSSLOWCERTCertificate *cert =
nsslowcert_FindCertByDERCert(certHandle,derCert);
lg_searchSingleCert(&certData,cert);
} else if (name->data != NULL) {
char *tmp_name = (char*)PORT_Alloc(name->len+1);
int count;
if (tmp_name == NULL) {
return;
}
PORT_Memcpy(tmp_name,name->data,name->len);
tmp_name[name->len] = 0;
count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
lg_CertSetupData(&certData,count);
nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
lg_cert_collect, &certData);
PORT_Free(tmp_name);
} else if (derSubject->data != NULL) {
int count;
count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
lg_CertSetupData(&certData,count);
nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
lg_cert_collect, &certData);
} else if ((issuerSN->derIssuer.data != NULL) &&
(issuerSN->serialNumber.data != NULL)) {
if (classFlags & LG_CERT) {
NSSLOWCERTCertificate *cert =
nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
lg_searchSingleCert(&certData,cert);
}
if (classFlags & LG_TRUST) {
NSSLOWCERTTrust *trust =
nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
if (trust) {
lg_addHandle(handles,
lg_mkHandle(sdb,&trust->dbKey,LG_TOKEN_TYPE_TRUST));
nsslowcert_DestroyTrust(trust);
}
}
} else if (email->data != NULL) {
char *tmp_name = (char*)PORT_Alloc(email->len+1);
certDBEntrySMime *entry = NULL;
if (tmp_name == NULL) {
return;
}
PORT_Memcpy(tmp_name,email->data,email->len);
tmp_name[email->len] = 0;
entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
if (entry) {
int count;
SECItem *subjectName = &entry->subjectName;
count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
lg_CertSetupData(&certData,count);
nsslowcert_TraversePermCertsForSubject(certHandle, subjectName,
lg_cert_collect, &certData);
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
}
PORT_Free(tmp_name);
} else {
/* we aren't filtering the certs, we are working on all, so turn
* on the strict filters. */
certData.strict = PR_TRUE;
lg_CertSetupData(&certData,LG_SEARCH_BLOCK_SIZE);
nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
}
/*
* build the handles
*/
for (i=0 ; i < certData.cert_count ; i++) {
NSSLOWCERTCertificate *cert = certData.certs[i];
/* if we filtered it would have been on the stuff above */
if (classFlags & LG_CERT) {
lg_addHandle(handles,
lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT));
}
if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
lg_addHandle(handles,
lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST));
}
nsslowcert_DestroyCertificate(cert);
}
if (certData.certs) PORT_Free(certData.certs);
return;
}
static SECStatus
lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
{
lgEntryData *smimeData;
SDB *sdb;
smimeData = (lgEntryData *)arg;
sdb = smimeData->sdb;
if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME,
smimeData->template, smimeData->templ_count)) {
lg_addHandle(smimeData->searchHandles,
lg_mkHandle(sdb,key,LG_TOKEN_TYPE_SMIME));
}
return(SECSuccess);
}
static void
lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles,
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
{
NSSLOWCERTCertDBHandle *certHandle = NULL;
certDBEntrySMime *entry;
certHandle = lg_getCertDB(sdb);
if (certHandle == NULL) return;
if (email->data != NULL) {
char *tmp_name = (char*)PORT_Alloc(email->len+1);
if (tmp_name == NULL) {
return;
}
PORT_Memcpy(tmp_name,email->data,email->len);
tmp_name[email->len] = 0;
entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
if (entry) {
SECItem emailKey;
emailKey.data = (unsigned char *)tmp_name;
emailKey.len = PORT_Strlen(tmp_name)+1;
emailKey.type = 0;
lg_addHandle(handles,
lg_mkHandle(sdb,&emailKey,LG_TOKEN_TYPE_SMIME));
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
}
PORT_Free(tmp_name);
} else {
/* traverse */
lgEntryData smimeData;
/* traverse */
smimeData.sdb = sdb;
smimeData.searchHandles = handles;
smimeData.template = pTemplate;
smimeData.templ_count = ulCount;
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile,
lg_smime_collect, (void *)&smimeData);
}
return;
}
static CK_RV
lg_searchTokenList(SDB *sdb, SDBFind *search,
const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
{
int i;
PRBool isKrl = PR_FALSE;
SECItem derCert = { siBuffer, NULL, 0 };
SECItem derSubject = { siBuffer, NULL, 0 };
SECItem name = { siBuffer, NULL, 0 };
SECItem email = { siBuffer, NULL, 0 };
SECItem key_id = { siBuffer, NULL, 0 };
SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
SECItem cert_md5_hash = { siBuffer, NULL, 0 };
NSSLOWCERTIssuerAndSN issuerSN = {
{ siBuffer, NULL, 0 },
{ siBuffer, NULL, 0 }
};
SECItem *copy = NULL;
CK_CERTIFICATE_TYPE certType;
CK_OBJECT_CLASS objectClass;
CK_RV crv;
unsigned long classFlags =
LG_CERT|LG_TRUST|LG_PRIVATE|LG_PUBLIC|LG_KEY|LG_SMIME|LG_CRL;
if (lg_getCertDB(sdb) == NULL) {
classFlags = LG_PRIVATE|LG_KEY;
} else {
classFlags = LG_CERT|LG_TRUST|LG_PUBLIC|LG_SMIME|LG_CRL;
}
/*
* look for things to search on token objects for. If the right options
* are specified, we can use them as direct indeces into the database
* (rather than using linear searches. We can also use the attributes to
* limit the kinds of objects we are searching for. Later we can use this
* array to filter the remaining objects more finely.
*/
for (i=0 ;classFlags && i < (int)ulCount; i++) {
switch (pTemplate[i].type) {
case CKA_SUBJECT:
copy = &derSubject;
classFlags &= (LG_CERT|LG_PRIVATE|LG_PUBLIC|LG_SMIME|LG_CRL);
break;
case CKA_ISSUER:
copy = &issuerSN.derIssuer;
classFlags &= (LG_CERT|LG_TRUST);
break;
case CKA_SERIAL_NUMBER:
copy = &issuerSN.serialNumber;
classFlags &= (LG_CERT|LG_TRUST);
break;
case CKA_VALUE:
copy = &derCert;
classFlags &= (LG_CERT|LG_CRL|LG_SMIME);
break;
case CKA_LABEL:
copy = &name;
break;
case CKA_NETSCAPE_EMAIL:
copy = &email;
classFlags &= LG_SMIME|LG_CERT;
break;
case CKA_NETSCAPE_SMIME_TIMESTAMP:
classFlags &= LG_SMIME;
break;
case CKA_CLASS:
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
if (crv != CKR_OK) {
classFlags = 0;
break;;
}
switch (objectClass) {
case CKO_CERTIFICATE:
classFlags &= LG_CERT;
break;
case CKO_NETSCAPE_TRUST:
classFlags &= LG_TRUST;
break;
case CKO_NETSCAPE_CRL:
classFlags &= LG_CRL;
break;
case CKO_NETSCAPE_SMIME:
classFlags &= LG_SMIME;
break;
case CKO_PRIVATE_KEY:
classFlags &= LG_PRIVATE;
break;
case CKO_PUBLIC_KEY:
classFlags &= LG_PUBLIC;
break;
case CKO_SECRET_KEY:
classFlags &= LG_KEY;
break;
default:
classFlags = 0;
break;
}
break;
case CKA_PRIVATE:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0;
}
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
classFlags &= (LG_PRIVATE|LG_KEY);
} else {
classFlags &= ~(LG_PRIVATE|LG_KEY);
}
break;
case CKA_SENSITIVE:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0;
}
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
classFlags &= (LG_PRIVATE|LG_KEY);
} else {
classFlags = 0;
}
break;
case CKA_TOKEN:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0;
}
if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
classFlags = 0;
}
break;
case CKA_CERT_SHA1_HASH:
classFlags &= LG_TRUST;
copy = &cert_sha1_hash; break;
case CKA_CERT_MD5_HASH:
classFlags &= LG_TRUST;
copy = &cert_md5_hash; break;
case CKA_CERTIFICATE_TYPE:
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1,&certType);
if (crv != CKR_OK) {
classFlags = 0;
}
classFlags &= LG_CERT;
if (certType != CKC_X_509) {
classFlags = 0;
}
break;
case CKA_ID:
copy = &key_id;
classFlags &= (LG_CERT|LG_PRIVATE|LG_KEY|LG_PUBLIC);
break;
case CKA_NETSCAPE_KRL:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0;
}
classFlags &= LG_CRL;
isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
break;
case CKA_MODIFIABLE:
break;
case CKA_KEY_TYPE:
case CKA_DERIVE:
classFlags &= LG_PUBLIC|LG_PRIVATE|LG_KEY;
break;
case CKA_VERIFY_RECOVER:
classFlags &= LG_PUBLIC;
break;
case CKA_SIGN_RECOVER:
classFlags &= LG_PRIVATE;
break;
case CKA_ENCRYPT:
case CKA_VERIFY:
case CKA_WRAP:
classFlags &= LG_PUBLIC|LG_KEY;
break;
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_UNWRAP:
case CKA_ALWAYS_SENSITIVE:
case CKA_EXTRACTABLE:
case CKA_NEVER_EXTRACTABLE:
classFlags &= LG_PRIVATE|LG_KEY;
break;
/* can't be a certificate if it doesn't match one of the above
* attributes */
default:
classFlags = 0;
break;
}
if (copy) {
copy->data = (unsigned char*)pTemplate[i].pValue;
copy->len = pTemplate[i].ulValueLen;
}
copy = NULL;
}
/* certs */
if (classFlags & (LG_CERT|LG_TRUST)) {
lg_searchCertsAndTrust(sdb,&derCert,&name,&derSubject,
&issuerSN, &email,classFlags,search,
pTemplate, ulCount);
}
/* keys */
if (classFlags & (LG_PRIVATE|LG_PUBLIC|LG_KEY)) {
PRBool mustStrict = ((classFlags & LG_KEY) != 0) && (name.len != 0);
lg_searchKeys(sdb, &key_id, classFlags, search,
mustStrict, pTemplate, ulCount);
}
/* crl's */
if (classFlags & LG_CRL) {
lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search,
pTemplate, ulCount);
}
/* Add S/MIME entry stuff */
if (classFlags & LG_SMIME) {
lg_searchSMime(sdb, &email, search, pTemplate, ulCount);
}
return CKR_OK;
}
/* lg_FindObjectsInit initializes a search for token and session objects
* that match a template. */
CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
CK_ULONG ulCount, SDBFind **retSearch)
{
SDBFind *search;
CK_RV crv = CKR_OK;
*retSearch = NULL;
search = (SDBFind *)PORT_Alloc(sizeof(SDBFind));
if (search == NULL) {
crv = CKR_HOST_MEMORY;
goto loser;
}
search->handles = (CK_OBJECT_HANDLE *)
PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE);
if (search->handles == NULL) {
crv = CKR_HOST_MEMORY;
goto loser;
}
search->index = 0;
search->size = 0;
search->array_size = LG_SEARCH_BLOCK_SIZE;
/* FIXME - do we still need to get Login state? */
crv = lg_searchTokenList(sdb, search, pTemplate, ulCount);
if (crv != CKR_OK) {
goto loser;
}
*retSearch = search;
return CKR_OK;
loser:
if (search) {
lg_FreeSearch(search);
}
return crv;
}
/* lg_FindObjects continues a search for token and session objects
* that match a template, obtaining additional object handles. */
CK_RV lg_FindObjects(SDB *sdb, SDBFind *search,
CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
CK_ULONG *pulObjectCount)
{
int transfer;
int left;
*pulObjectCount = 0;
left = search->size - search->index;
transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
if (transfer > 0) {
PORT_Memcpy(phObject,&search->handles[search->index],
transfer*sizeof(CK_OBJECT_HANDLE_PTR));
} else {
*phObject = CK_INVALID_HANDLE;
}
search->index += transfer;
*pulObjectCount = transfer;
return CKR_OK;
}
/* lg_FindObjectsFinal finishes a search for token and session objects. */
CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search)
{
if (search != NULL) {
lg_FreeSearch(search);
}
return CKR_OK;
}

View File

@@ -1,644 +0,0 @@
/*
* NSS utility functions
*
* ***** 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 ***** */
/* $Id: lginit.c,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
#include "lowkeyi.h"
#include "pcert.h"
#include "keydbi.h"
#include "lgdb.h"
typedef struct LGPrivateStr {
NSSLOWCERTCertDBHandle *certDB;
NSSLOWKEYDBHandle *keyDB;
PRLock *dbLock;
PLHashTable *hashTable;
} LGPrivate;
static char *
lg_certdb_name_cb(void *arg, int dbVersion)
{
const char *configdir = (const char *)arg;
const char *dbver;
char *smpname = NULL;
char *dbname = NULL;
switch (dbVersion) {
case 8:
dbver = "8";
break;
case 7:
dbver = "7";
break;
case 6:
dbver = "6";
break;
case 5:
dbver = "5";
break;
case 4:
default:
dbver = "";
break;
}
/* make sure we return something allocated with PORT_ so we have properly
* matched frees at the end */
smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
if (smpname) {
dbname = PORT_Strdup(smpname);
PR_smprintf_free(smpname);
}
return dbname;
}
static char *
lg_keydb_name_cb(void *arg, int dbVersion)
{
const char *configdir = (const char *)arg;
const char *dbver;
char *smpname = NULL;
char *dbname = NULL;
switch (dbVersion) {
case 4:
dbver = "4";
break;
case 3:
dbver = "3";
break;
case 1:
dbver = "1";
break;
case 2:
default:
dbver = "";
break;
}
smpname = PR_smprintf(KEY_DB_FMT, configdir, dbver);
if (smpname) {
dbname = PORT_Strdup(smpname);
PR_smprintf_free(smpname);
}
return dbname;
}
const char *
lg_EvaluateConfigDir(const char *configdir,char **appName)
{
if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
char *cdir;
*appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
if (*appName == NULL) {
return configdir;
}
cdir = *appName;
while (*cdir && *cdir != ':') {
cdir++;
}
if (*cdir == ':') {
*cdir = 0;
cdir++;
}
configdir = cdir;
}
return configdir;
}
static int rdbmapflags(int flags);
static rdbfunc lg_rdbfunc = NULL;
static rdbstatusfunc lg_rdbstatusfunc = NULL;
/* NOTE: SHLIB_SUFFIX is defined on the command line */
#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
DB * rdbopen(const char *appName, const char *prefix,
const char *type, int flags, int *status)
{
PRLibrary *lib;
DB *db;
if (lg_rdbfunc) {
db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
if (!db && status && lg_rdbstatusfunc) {
*status = (*lg_rdbstatusfunc)();
}
return db;
}
/*
* try to open the library.
*/
lib = PR_LoadLibrary(RDBLIB);
if (!lib) {
return NULL;
}
/* get the entry points */
lg_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
lg_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
if (lg_rdbfunc) {
db = (*lg_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
if (!db && status && lg_rdbstatusfunc) {
*status = (*lg_rdbstatusfunc)();
}
return db;
}
/* couldn't find the entry point, unload the library and fail */
PR_UnloadLibrary(lib);
return NULL;
}
/*
* the following data structures are from rdb.h.
*/
struct RDBStr {
DB db;
int (*xactstart)(DB *db);
int (*xactdone)(DB *db, PRBool abort);
int version;
int (*dbinitcomplete)(DB *db);
};
#define DB_RDB ((DBTYPE) 0xff)
#define RDB_RDONLY 1
#define RDB_RDWR 2
#define RDB_CREATE 4
static int
rdbmapflags(int flags) {
switch (flags) {
case NO_RDONLY:
return RDB_RDONLY;
case NO_RDWR:
return RDB_RDWR;
case NO_CREATE:
return RDB_CREATE;
default:
break;
}
return 0;
}
PRBool
db_IsRDB(DB *db)
{
return (PRBool) db->type == DB_RDB;
}
int
db_BeginTransaction(DB *db)
{
struct RDBStr *rdb = (struct RDBStr *)db;
if (db->type != DB_RDB) {
return 0;
}
return rdb->xactstart(db);
}
int
db_FinishTransaction(DB *db, PRBool abort)
{
struct RDBStr *rdb = (struct RDBStr *)db;
if (db->type != DB_RDB) {
return 0;
}
return rdb->xactdone(db, abort);
}
static DB *
lg_getRawDB(SDB *sdb)
{
NSSLOWCERTCertDBHandle *certDB;
NSSLOWKEYDBHandle *keyDB;
certDB = lg_getCertDB(sdb);
if (certDB) {
return certDB->permCertDB;
}
keyDB = lg_getKeyDB(sdb);
if (keyDB) {
return keyDB->db;
}
return NULL;
}
CK_RV
lg_Begin(SDB *sdb)
{
DB *db = lg_getRawDB(sdb);
int ret;
if (db == NULL) {
return CKR_GENERAL_ERROR; /* shouldn't happen */
}
ret = db_BeginTransaction(db);
if (ret != 0) {
return CKR_GENERAL_ERROR; /* could happen */
}
return CKR_OK;
}
CK_RV
lg_Commit(SDB *sdb)
{
DB *db = lg_getRawDB(sdb);
int ret;
if (db == NULL) {
return CKR_GENERAL_ERROR; /* shouldn't happen */
}
ret = db_FinishTransaction(db, PR_FALSE);
if (ret != 0) {
return CKR_GENERAL_ERROR; /* could happen */
}
return CKR_OK;
}
CK_RV
lg_Abort(SDB *sdb)
{
DB *db = lg_getRawDB(sdb);
int ret;
if (db == NULL) {
return CKR_GENERAL_ERROR; /* shouldn't happen */
}
ret = db_FinishTransaction(db, PR_TRUE);
if (ret != 0) {
return CKR_GENERAL_ERROR; /* could happen */
}
return CKR_OK;
}
int
db_InitComplete(DB *db)
{
struct RDBStr *rdb = (struct RDBStr *)db;
if (db->type != DB_RDB) {
return 0;
}
/* we should have added a version number to the RDBS structure. Since we
* didn't, we detect that we have and 'extended' structure if the rdbstatus
* func exists */
if (!lg_rdbstatusfunc) {
return 0;
}
return rdb->dbinitcomplete(db);
}
SECStatus
db_Copy(DB *dest,DB *src)
{
int ret;
DBT key,data;
ret = (*src->seq)(src, &key, &data, R_FIRST);
if (ret) {
return SECSuccess;
}
do {
(void)(*dest->put)(dest,&key,&data, R_NOOVERWRITE);
} while ( (*src->seq)(src, &key, &data, R_NEXT) == 0);
(void)(*dest->sync)(dest,0);
return SECSuccess;
}
static CK_RV
lg_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
NSSLOWCERTCertDBHandle **certdbPtr)
{
NSSLOWCERTCertDBHandle *certdb = NULL;
CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
SECStatus rv;
char * name = NULL;
char * appName = NULL;
if (prefix == NULL) {
prefix = "";
}
configdir = lg_EvaluateConfigDir(configdir, &appName);
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
if (name == NULL) goto loser;
certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
if (certdb == NULL)
goto loser;
certdb->ref = 1;
/* fix when we get the DB in */
rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
lg_certdb_name_cb, (void *)name, PR_FALSE);
if (rv == SECSuccess) {
crv = CKR_OK;
*certdbPtr = certdb;
certdb = NULL;
}
loser:
if (certdb) PR_Free(certdb);
if (name) PR_smprintf_free(name);
if (appName) PORT_Free(appName);
return crv;
}
static CK_RV
lg_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
NSSLOWKEYDBHandle **keydbPtr)
{
NSSLOWKEYDBHandle *keydb;
char * name = NULL;
char * appName = NULL;
if (prefix == NULL) {
prefix = "";
}
configdir = lg_EvaluateConfigDir(configdir, &appName);
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
if (name == NULL)
return CKR_HOST_MEMORY;
keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
lg_keydb_name_cb, (void *)name);
PR_smprintf_free(name);
if (appName) PORT_Free(appName);
if (keydb == NULL)
return CKR_NETSCAPE_KEYDB_FAILED;
*keydbPtr = keydb;
return CKR_OK;
}
/*
* Accessors for the private parts of the sdb structure.
*/
void
lg_DBLock(SDB *sdb)
{
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
PR_Lock(lgdb_p->dbLock);
}
void
lg_DBUnlock(SDB *sdb)
{
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
PR_Unlock(lgdb_p->dbLock);
}
PLHashTable *
lg_GetHashTable(SDB *sdb)
{
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
return lgdb_p->hashTable;
}
NSSLOWCERTCertDBHandle *
lg_getCertDB(SDB *sdb)
{
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
return lgdb_p->certDB;
}
NSSLOWKEYDBHandle *
lg_getKeyDB(SDB *sdb)
{
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
return lgdb_p->keyDB;
}
CK_RV
lg_Close(SDB *sdb)
{
LGPrivate *lgdb_p = (LGPrivate *)sdb->private;
if (lgdb_p) {
if (lgdb_p->certDB) {
nsslowcert_ClosePermCertDB(lgdb_p->certDB);
} else if (lgdb_p->keyDB) {
nsslowkey_CloseKeyDB(lgdb_p->keyDB);
}
if (lgdb_p->dbLock) {
PR_DestroyLock(lgdb_p->dbLock);
}
if (lgdb_p->hashTable) {
PL_HashTableDestroy(lgdb_p->hashTable);
}
PORT_Free(lgdb_p);
}
PORT_Free(sdb);
return CKR_OK;
}
static PLHashNumber
lg_HashNumber(const void *key)
{
return (PLHashNumber) key;
}
/*
* helper function to wrap a NSSLOWCERTCertDBHandle or a NSSLOWKEYDBHandle
* with and sdb structure.
*/
CK_RV
lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
NSSLOWKEYDBHandle *keydbPtr)
{
SDB *sdb = NULL;
LGPrivate *lgdb_p = NULL;
CK_RV error = CKR_HOST_MEMORY;
*pSdb = NULL;
sdb = (SDB *) PORT_Alloc(sizeof(SDB));
if (sdb == NULL) {
goto loser;
}
lgdb_p = (LGPrivate *) PORT_Alloc(sizeof(LGPrivate));
if (lgdb_p == NULL) {
goto loser;
}
/* invariant fields */
lgdb_p->certDB = certdbPtr;
lgdb_p->keyDB = keydbPtr;
lgdb_p->dbLock = PR_NewLock();
if (lgdb_p->dbLock == NULL) {
goto loser;
}
lgdb_p->hashTable = PL_NewHashTable(64, lg_HashNumber, PL_CompareValues,
SECITEM_HashCompare, NULL, 0);
if (lgdb_p->hashTable == NULL) {
goto loser;
}
sdb->sdb_type = SDB_LEGACY;
sdb->sdb_flags = flags;
sdb->private = lgdb_p;
sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
sdb->sdb_FindObjects = lg_FindObjects;
sdb->sdb_FindObjectsFinal = lg_FindObjectsFinal;
sdb->sdb_GetAttributeValue = lg_GetAttributeValue;
sdb->sdb_SetAttributeValue = lg_SetAttributeValue;
sdb->sdb_CreateObject = lg_CreateObject;
sdb->sdb_DestroyObject = lg_DestroyObject;
sdb->sdb_GetPWEntry = lg_GetPWEntry;
sdb->sdb_PutPWEntry = lg_PutPWEntry;
sdb->sdb_Begin = lg_Begin;
sdb->sdb_Commit = lg_Commit;
sdb->sdb_Abort = lg_Abort;
sdb->sdb_Close = lg_Reset;
sdb->sdb_Close = lg_Close;
*pSdb = sdb;
return CKR_OK;
loser:
if (sdb) {
PORT_Free(sdb);
}
if (lgdb_p) {
if (lgdb_p->dbLock) {
PR_DestroyLock(lgdb_p->dbLock);
}
if (lgdb_p->hashTable) {
PL_HashTableDestroy(lgdb_p->hashTable);
}
PORT_Free(lgdb_p);
}
return error;
}
extern SECStatus secoid_Init(void); /* util *REALLY* needs
* to be a shared library */
/*
* OK there are now lots of options here, lets go through them all:
*
* configdir - base directory where all the cert, key, and module datbases live.
* certPrefix - prefix added to the beginning of the cert database example: "
* "https-server1-"
* keyPrefix - prefix added to the beginning of the key database example: "
* "https-server1-"
* secmodName - name of the security module database (usually "secmod.db").
* readOnly - Boolean: true if the databases are to be openned read only.
* nocertdb - Don't open the cert DB and key DB's, just initialize the
* Volatile certdb.
* nomoddb - Don't open the security module DB, just initialize the
* PKCS #11 module.
* forceOpen - Continue to force initializations even if the databases cannot
* be opened.
*/
CK_RV
legacy_Open(const char *configdir, const char *certPrefix,
const char *keyPrefix, int certVersion, int keyVersion,
int flags, SDB **certDB, SDB **keyDB)
{
CK_RV crv = CKR_OK;
PRBool readOnly = (flags == SDB_RDONLY)? PR_TRUE: PR_FALSE;
secoid_Init();
nsslowcert_InitLocks();
if (keyDB) *keyDB = NULL;
if (certDB) *certDB = NULL;
if (certDB) {
NSSLOWCERTCertDBHandle *certdbPtr;
crv = lg_OpenCertDB(configdir, certPrefix, readOnly, &certdbPtr);
if (crv != CKR_OK) {
goto loser;
}
crv = lg_init(certDB, flags, certdbPtr, NULL);
if (crv != CKR_OK) {
nsslowcert_ClosePermCertDB(certdbPtr);
goto loser;
}
}
if (keyDB) {
NSSLOWKEYDBHandle *keydbPtr;
crv = lg_OpenKeyDB(configdir, keyPrefix, readOnly, &keydbPtr);
if (crv != CKR_OK) {
goto loser;
}
crv = lg_init(keyDB, flags, NULL, keydbPtr);
if (crv != CKR_OK) {
nsslowkey_CloseKeyDB(keydbPtr);
goto loser;
}
if (certDB && *certDB) {
LGPrivate *lgdb_p = (LGPrivate *)(*certDB)->private;
lgdb_p->keyDB = keydbPtr;
}
}
loser:
if (crv != CKR_OK) {
if (keyDB && *keyDB) {
lg_Close(*keyDB);
*keyDB = NULL;
}
if (certDB && *certDB) {
lg_Close(*certDB);
*certDB = NULL;
}
}
return crv;
}
CK_RV
legacy_Shutdown(void)
{
nsslowcert_DestroyFreeLists();
nsslowcert_DestroyGlobalLocks();
}

View File

@@ -1,424 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 ***** */
#include "lgdb.h"
#include "secerr.h"
#include "lgglue.h"
/*
* ******************** Attribute Utilities *******************************
*/
/*
* look up and attribute structure from a type and Object structure.
* The returned attribute is referenced and needs to be freed when
* it is no longer needed.
*/
const CK_ATTRIBUTE *
lg_FindAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
CK_ULONG count )
{
int i;
for (i=0; i < count; i++) {
if (templ[i].type == type) {
return &templ[i];
}
}
return NULL;
}
/*
* return true if object has attribute
*/
PRBool
lg_hasAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
CK_ULONG count )
{
if (lg_FindAttribute(type, templ, count) == NULL) {
return PR_FALSE;
}
return PR_TRUE;
}
/*
* copy an attribute into a SECItem. Secitem is allocated in the specified
* arena.
*/
CK_RV
lg_Attribute2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item)
{
int len;
const CK_ATTRIBUTE *attribute;
attribute = lg_FindAttribute(type, templ, count);
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
len = attribute->ulValueLen;
if (arena) {
item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
} else {
item->data = (unsigned char *) PORT_Alloc(len);
}
if (item->data == NULL) {
return CKR_HOST_MEMORY;
}
item->len = len;
PORT_Memcpy(item->data, attribute->pValue, len);
return CKR_OK;
}
/*
* copy an unsigned attribute into a SECItem. Secitem is allocated in
* the specified arena.
*/
CK_RV
lg_Attribute2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item)
{
const CK_ATTRIBUTE *attribute;
item->data = NULL;
attribute = lg_FindAttribute(type, templ, count);
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
(void)SECITEM_AllocItem(arena, item, attribute->ulValueLen);
if (item->data == NULL) {
return CKR_HOST_MEMORY;
}
PORT_Memcpy(item->data, attribute->pValue, item->len);
return CKR_OK;
}
/*
* copy an unsigned attribute into a SECItem. Secitem is allocated in
* the specified arena.
*/
CK_RV
lg_PrivAttr2SSecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item, SDB *sdbpw)
{
const CK_ATTRIBUTE *attribute;
SECItem epki, *dest = NULL;
SECStatus rv;
item->data = NULL;
attribute = lg_FindAttribute(type, templ, count);
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
epki.data = attribute->pValue;
epki.len = attribute->ulValueLen;
rv = lg_util_decrypt(sdbpw, &epki, &dest);
if (rv != SECSuccess) {
return CKR_USER_NOT_LOGGED_IN;
}
(void)SECITEM_AllocItem(arena, item, dest->len);
if (item->data == NULL) {
SECITEM_FreeItem(dest, PR_TRUE);
return CKR_HOST_MEMORY;
}
PORT_Memcpy(item->data, dest->data, item->len);
SECITEM_FreeItem(dest, PR_TRUE);
return CKR_OK;
}
CK_RV
lg_PrivAttr2SecItem(PLArenaPool *arena, CK_ATTRIBUTE_TYPE type,
const CK_ATTRIBUTE *templ, CK_ULONG count,
SECItem *item, SDB *sdbpw)
{
return lg_PrivAttr2SSecItem(arena, type, templ, count, item, sdbpw);
}
/*
* this is only valid for CK_BBOOL type attributes. Return the state
* of that attribute.
*/
PRBool
lg_isTrue(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
const CK_ATTRIBUTE *attribute;
PRBool tok = PR_FALSE;
attribute=lg_FindAttribute(type, templ, count);
if (attribute == NULL) { return PR_FALSE; }
tok = (PRBool)(*(CK_BBOOL *)attribute->pValue);
return tok;
}
/*
* return a null terminated string from attribute 'type'. This string
* is allocated and needs to be freed with PORT_Free() When complete.
*/
char *
lg_getString(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ, CK_ULONG count)
{
const CK_ATTRIBUTE *attribute;
char *label = NULL;
attribute = lg_FindAttribute(type, templ, count);
if (attribute == NULL) return NULL;
if (attribute->pValue != NULL) {
label = (char *) PORT_Alloc(attribute->ulValueLen+1);
if (label == NULL) {
return NULL;
}
PORT_Memcpy(label,attribute->pValue, attribute->ulValueLen);
label[attribute->ulValueLen] = 0;
}
return label;
}
CK_RV
lg_GetULongAttribute(CK_ATTRIBUTE_TYPE type, const CK_ATTRIBUTE *templ,
CK_ULONG count, CK_ULONG *longData)
{
const CK_ATTRIBUTE *attribute;
CK_ULONG value = 0;
const unsigned char *data;
int i;
attribute = lg_FindAttribute(type, templ, count);
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
if (attribute->ulValueLen != sizeof(CK_ULONG)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
data = (const unsigned char *)attribute->pValue;
for (i=0; i < 4; i++) {
value |= (CK_ULONG)(data[i]) << ((3-i)*8);
}
*longData = value;
return CKR_OK;
}
/*
* ******************** Object Utilities *******************************
*/
SECStatus
lg_deleteTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
{
SECItem *item;
PRBool rem;
PLHashTable *hashTable= lg_GetHashTable(sdb);
item = (SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
rem = PL_HashTableRemove(hashTable,(void *)handle) ;
if (rem && item) {
SECITEM_FreeItem(item,PR_TRUE);
}
return rem ? SECSuccess : SECFailure;
}
/* must be called holding lg_DBLock(sdb) */
static SECStatus
lg_addTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle, SECItem *key)
{
PLHashEntry *entry;
SECItem *item;
PLHashTable *hashTable= lg_GetHashTable(sdb);
item = SECITEM_DupItem(key);
if (item == NULL) {
return SECFailure;
}
entry = PL_HashTableAdd(hashTable,(void *)handle,item);
if (entry == NULL) {
SECITEM_FreeItem(item,PR_TRUE);
return SECFailure;
}
return SECSuccess;
}
/* must be called holding lg_DBLock(sdb) */
const SECItem *
lg_lookupTokenKeyByHandle(SDB *sdb, CK_OBJECT_HANDLE handle)
{
PLHashTable *hashTable= lg_GetHashTable(sdb);
return (const SECItem *)PL_HashTableLookup(hashTable, (void *)handle);
}
static PRIntn
lg_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
{
SECItem *item = (SECItem *)entry->value;
SECITEM_FreeItem(item, PR_TRUE);
return HT_ENUMERATE_NEXT;
}
CK_RV
LG_ClearTokenKeyHashTable(SDB *sdb)
{
PLHashTable *hashTable;
lg_DBLock(sdb);
hashTable= lg_GetHashTable(sdb);
PL_HashTableEnumerateEntries(hashTable, lg_freeHashItem, NULL);
lg_DBLock(sdb);
return CKR_OK;
}
/*
* handle Token Object stuff
*/
static void
lg_XORHash(unsigned char *key, unsigned char *dbkey, int len)
{
int i;
PORT_Memset(key, 0, 4);
for (i=0; i < len-4; i += 4) {
key[0] ^= dbkey[i];
key[1] ^= dbkey[i+1];
key[2] ^= dbkey[i+2];
key[3] ^= dbkey[i+3];
}
}
/* Make a token handle for an object and record it so we can find it again */
CK_OBJECT_HANDLE
lg_mkHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
{
unsigned char hashBuf[4];
CK_OBJECT_HANDLE handle;
const SECItem *key;
handle = class;
/* there is only one KRL, use a fixed handle for it */
if (handle != LG_TOKEN_KRL_HANDLE) {
lg_XORHash(hashBuf,dbKey->data,dbKey->len);
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
(hashBuf[2] << 8) | hashBuf[3];
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
/* we have a CRL who's handle has randomly matched the reserved KRL
* handle, increment it */
if (handle == LG_TOKEN_KRL_HANDLE) {
handle++;
}
}
lg_DBLock(sdb);
while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
if (SECITEM_ItemsAreEqual(key,dbKey)) {
lg_DBUnlock(sdb);
return handle;
}
handle++;
}
lg_addTokenKeyByHandle(sdb,handle,dbKey);
lg_DBUnlock(sdb);
return handle;
}
PRBool
lg_poisonHandle(SDB *sdb, SECItem *dbKey, CK_OBJECT_HANDLE class)
{
unsigned char hashBuf[4];
CK_OBJECT_HANDLE handle;
const SECItem *key;
handle = class;
/* there is only one KRL, use a fixed handle for it */
if (handle != LG_TOKEN_KRL_HANDLE) {
lg_XORHash(hashBuf,dbKey->data,dbKey->len);
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
(hashBuf[2] << 8) | hashBuf[3];
handle = class | (handle & ~(LG_TOKEN_TYPE_MASK|LG_TOKEN_MASK));
/* we have a CRL who's handle has randomly matched the reserved KRL
* handle, increment it */
if (handle == LG_TOKEN_KRL_HANDLE) {
handle++;
}
}
lg_DBLock(sdb);
while ((key = lg_lookupTokenKeyByHandle(sdb,handle)) != NULL) {
if (SECITEM_ItemsAreEqual(key,dbKey)) {
key->data[0] ^= 0x80;
lg_DBUnlock(sdb);
return PR_TRUE;
}
handle++;
}
lg_DBUnlock(sdb);
return PR_FALSE;
}
static LGEncryptFunc lg_encrypt_stub = NULL;
static LGDecryptFunc lg_decrypt_stub = NULL;
void
legacy_SetCryptFunctions(LGEncryptFunc enc, LGDecryptFunc dec)
{
lg_encrypt_stub = enc;
lg_decrypt_stub = dec;
}
SECStatus lg_util_encrypt(PLArenaPool *arena, SDB *sdb,
SECItem *plainText, SECItem **cipherText)
{
if (lg_encrypt_stub == NULL) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return (*lg_encrypt_stub)(arena, sdb, plainText, cipherText);
}
SECStatus lg_util_decrypt(SDB *sdb, SECItem *cipherText, SECItem **plainText)
{
if (lg_decrypt_stub == NULL) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return (*lg_decrypt_stub)(sdb, cipherText, plainText);
}

View File

@@ -1,824 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 ***** */
/*
* Certificate handling code
*
* $Id: lowcert.c,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
*/
#include "seccomon.h"
#include "secder.h"
#include "nssilock.h"
#include "lowkeyi.h"
#include "secasn1.h"
#include "secoid.h"
#include "secerr.h"
#include "pcert.h"
static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
{ SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
SECOID_AlgorithmIDTemplate },
{ SEC_ASN1_BIT_STRING,
offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
{ 0, }
};
static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
{ 0, }
};
static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
{ 0, }
};
static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
{ 0, }
};
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
static void
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.rsa.modulus.type = siUnsignedInteger;
pubk->u.rsa.publicExponent.type = siUnsignedInteger;
}
static void
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.dsa.publicValue.type = siUnsignedInteger;
pubk->u.dsa.params.prime.type = siUnsignedInteger;
pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
pubk->u.dsa.params.base.type = siUnsignedInteger;
}
static void
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.dh.prime.type = siUnsignedInteger;
pubk->u.dh.base.type = siUnsignedInteger;
pubk->u.dh.publicValue.type = siUnsignedInteger;
}
/*
* simple cert decoder to avoid the cost of asn1 engine
*/
static unsigned char *
nsslowcert_dataStart(unsigned char *buf, unsigned int length,
unsigned int *data_length, PRBool includeTag,
unsigned char* rettag) {
unsigned char tag;
unsigned int used_length= 0;
tag = buf[used_length++];
if (rettag) {
*rettag = tag;
}
/* blow out when we come to the end */
if (tag == 0) {
return NULL;
}
*data_length = buf[used_length++];
if (*data_length&0x80) {
int len_count = *data_length & 0x7f;
*data_length = 0;
while (len_count-- > 0) {
*data_length = (*data_length << 8) | buf[used_length++];
}
}
if (*data_length > (length-used_length) ) {
*data_length = length-used_length;
return NULL;
}
if (includeTag) *data_length += used_length;
return (buf + (includeTag ? 0 : used_length));
}
static void SetTimeType(SECItem* item, unsigned char tagtype)
{
switch (tagtype) {
case SEC_ASN1_UTC_TIME:
item->type = siUTCTime;
break;
case SEC_ASN1_GENERALIZED_TIME:
item->type = siGeneralizedTime;
break;
default:
PORT_Assert(0);
break;
}
}
static int
nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
SECItem *notBefore, SECItem *notAfter)
{
unsigned char tagtype;
notBefore->data = nsslowcert_dataStart(buf,buf_length,
&notBefore->len,PR_FALSE, &tagtype);
if (notBefore->data == NULL) return SECFailure;
SetTimeType(notBefore, tagtype);
buf_length -= (notBefore->data-buf) + notBefore->len;
buf = notBefore->data + notBefore->len;
notAfter->data = nsslowcert_dataStart(buf,buf_length,
&notAfter->len,PR_FALSE, &tagtype);
if (notAfter->data == NULL) return SECFailure;
SetTimeType(notAfter, tagtype);
return SECSuccess;
}
static int
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
SECItem *valid, SECItem *subjkey, SECItem *extensions)
{
unsigned char *buf;
unsigned int buf_length;
unsigned char *dummy;
unsigned int dummylen;
/* get past the signature wrap */
buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
if (buf == NULL) return SECFailure;
/* get into the raw cert data */
buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
if (buf == NULL) return SECFailure;
/* skip past any optional version number */
if ((buf[0] & 0xa0) == 0xa0) {
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy-buf) + dummylen;
buf = dummy + dummylen;
}
/* serial number */
if (derSN) {
derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
}
serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
if (serial->data == NULL) return SECFailure;
buf_length -= (serial->data-buf) + serial->len;
buf = serial->data + serial->len;
/* skip the OID */
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy-buf) + dummylen;
buf = dummy + dummylen;
/* issuer */
issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
if (issuer->data == NULL) return SECFailure;
buf_length -= (issuer->data-buf) + issuer->len;
buf = issuer->data + issuer->len;
/* only wanted issuer/SN */
if (valid == NULL) {
return SECSuccess;
}
/* validity */
valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
if (valid->data == NULL) return SECFailure;
buf_length -= (valid->data-buf) + valid->len;
buf = valid->data + valid->len;
/*subject */
subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
if (subject->data == NULL) return SECFailure;
buf_length -= (subject->data-buf) + subject->len;
buf = subject->data + subject->len;
/* subject key info */
subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
if (subjkey->data == NULL) return SECFailure;
buf_length -= (subjkey->data-buf) + subjkey->len;
buf = subjkey->data + subjkey->len;
extensions->data = NULL;
extensions->len = 0;
while (buf_length > 0) {
/* EXTENSIONS */
if (buf[0] == 0xa3) {
extensions->data = nsslowcert_dataStart(buf,buf_length,
&extensions->len, PR_FALSE, NULL);
break;
}
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE,NULL);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy - buf) + dummylen;
buf = dummy + dummylen;
}
return SECSuccess;
}
static SECStatus
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
{
int rv;
NSSLOWCERTValidity validity;
rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
&validity.notBefore,&validity.notAfter);
if (rv != SECSuccess) {
return rv;
}
/* convert DER not-before time */
rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
if (rv) {
return(SECFailure);
}
/* convert DER not-after time */
rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
if (rv) {
return(SECFailure);
}
return(SECSuccess);
}
/*
* is certa newer than certb? If one is expired, pick the other one.
*/
PRBool
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
{
PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
SECStatus rv;
PRBool newerbefore, newerafter;
rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
if ( rv != SECSuccess ) {
return(PR_FALSE);
}
rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
if ( rv != SECSuccess ) {
return(PR_TRUE);
}
newerbefore = PR_FALSE;
if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
newerbefore = PR_TRUE;
}
newerafter = PR_FALSE;
if ( LL_CMP(notAfterA, >, notAfterB) ) {
newerafter = PR_TRUE;
}
if ( newerbefore && newerafter ) {
return(PR_TRUE);
}
if ( ( !newerbefore ) && ( !newerafter ) ) {
return(PR_FALSE);
}
/* get current time */
now = PR_Now();
if ( newerbefore ) {
/* cert A was issued after cert B, but expires sooner */
/* if A is expired, then pick B */
if ( LL_CMP(notAfterA, <, now ) ) {
return(PR_FALSE);
}
return(PR_TRUE);
} else {
/* cert B was issued after cert A, but expires sooner */
/* if B is expired, then pick A */
if ( LL_CMP(notAfterB, <, now ) ) {
return(PR_TRUE);
}
return(PR_FALSE);
}
}
#define SOFT_DEFAULT_CHUNKSIZE 2048
static SECStatus
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena,
SECItem *issuer, SECItem *sn, SECItem *key)
{
unsigned int len = sn->len + issuer->len;
if (!arena) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto loser;
}
key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
if ( !key->data ) {
goto loser;
}
key->len = len;
/* copy the serialNumber */
PORT_Memcpy(key->data, sn->data, sn->len);
/* copy the issuer */
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
return(SECSuccess);
loser:
return(SECFailure);
}
static SECStatus
nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
{
unsigned int len = sn->len + issuer->len;
key->data = pkcs11_allocStaticData(len, space, spaceLen);
if ( !key->data ) {
goto loser;
}
key->len = len;
/* copy the serialNumber */
PORT_Memcpy(key->data, sn->data, sn->len);
/* copy the issuer */
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
return(SECSuccess);
loser:
return(SECFailure);
}
static char *
nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
{
unsigned char *buf;
unsigned int buf_length;
/* unwrap outer sequence */
buf=nsslowcert_dataStart(derDN->data,derDN->len,&buf_length,PR_FALSE,NULL);
if (buf == NULL) return NULL;
/* Walk each RDN */
while (buf_length > 0) {
unsigned char *rdn;
unsigned int rdn_length;
/* grab next rdn */
rdn=nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE, NULL);
if (rdn == NULL) { return NULL; }
buf_length -= (rdn - buf) + rdn_length;
buf = rdn+rdn_length;
while (rdn_length > 0) {
unsigned char *ava;
unsigned int ava_length;
unsigned char *oid;
unsigned int oid_length;
unsigned char *name;
unsigned int name_length;
SECItem oidItem;
SECOidTag type;
/* unwrap the ava */
ava=nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE,
NULL);
if (ava == NULL) return NULL;
rdn_length -= (ava-rdn)+ava_length;
rdn = ava + ava_length;
oid=nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE,
NULL);
if (oid == NULL) { return NULL; }
ava_length -= (oid-ava)+oid_length;
ava = oid+oid_length;
name=nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE,
NULL);
if (oid == NULL) { return NULL; }
ava_length -= (name-ava)+name_length;
ava = name+name_length;
oidItem.data = oid;
oidItem.len = oid_length;
type = SECOID_FindOIDTag(&oidItem);
if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
(type == SEC_OID_RFC1274_MAIL)) {
/* Email is supposed to be IA5String, so no
* translation necessary */
char *emailAddr;
emailAddr = (char *)pkcs11_copyStaticData(name,name_length+1,
(unsigned char *)space,len);
if (emailAddr) {
emailAddr[name_length] = 0;
}
return emailAddr;
}
}
}
return NULL;
}
static char *
nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
unsigned int len)
{
unsigned char *exts;
unsigned int exts_length;
/* unwrap the sequence */
exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
&exts_length, PR_FALSE, NULL);
/* loop through extension */
while (exts && exts_length > 0) {
unsigned char * ext;
unsigned int ext_length;
unsigned char *oid;
unsigned int oid_length;
unsigned char *nameList;
unsigned int nameList_length;
SECItem oidItem;
SECOidTag type;
ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
PR_FALSE, NULL);
if (ext == NULL) { break; }
exts_length -= (ext - exts) + ext_length;
exts = ext+ext_length;
oid=nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE, NULL);
if (oid == NULL) { break; }
ext_length -= (oid - ext) + oid_length;
ext = oid+oid_length;
oidItem.data = oid;
oidItem.len = oid_length;
type = SECOID_FindOIDTag(&oidItem);
/* get Alt Extension */
if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
continue;
}
/* skip passed the critical flag */
if (ext[0] == 0x01) { /* BOOLEAN */
unsigned char *dummy;
unsigned int dummy_length;
dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
PR_FALSE, NULL);
if (dummy == NULL) { break; }
ext_length -= (dummy - ext) + dummy_length;
ext = dummy+dummy_length;
}
/* unwrap the name list */
nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
PR_FALSE, NULL);
if (nameList == NULL) { break; }
ext_length -= (nameList - ext) + nameList_length;
ext = nameList+nameList_length;
nameList = nsslowcert_dataStart(nameList, nameList_length,
&nameList_length, PR_FALSE, NULL);
/* loop through the name list */
while (nameList && nameList_length > 0) {
unsigned char *thisName;
unsigned int thisName_length;
thisName = nsslowcert_dataStart(nameList, nameList_length,
&thisName_length, PR_FALSE, NULL);
if (thisName == NULL) { break; }
if (nameList[0] == 0xa2) { /* DNS Name */
SECItem dn;
char *emailAddr;
dn.data = thisName;
dn.len = thisName_length;
emailAddr = nsslowcert_EmailName(&dn, space, len);
if (emailAddr) {
return emailAddr;
}
}
if (nameList[0] == 0x81) { /* RFC 822name */
char *emailAddr;
emailAddr = (char *)pkcs11_copyStaticData(thisName,
thisName_length+1, (unsigned char *)space,len);
if (emailAddr) {
emailAddr[thisName_length] = 0;
}
return emailAddr;
}
nameList_length -= (thisName-nameList) + thisName_length;
nameList = thisName + thisName_length;
}
break;
}
return NULL;
}
static char *
nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
{
char *emailAddr = NULL;
char *str;
emailAddr = nsslowcert_EmailName(&cert->derSubject,cert->emailAddrSpace,
sizeof(cert->emailAddrSpace));
/* couldn't find the email address in the DN, check the subject Alt name */
if (!emailAddr && cert->extensions.data) {
emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
sizeof(cert->emailAddrSpace));
}
/* make it lower case */
str = emailAddr;
while ( str && *str ) {
*str = tolower( *str );
str++;
}
return emailAddr;
}
/*
* take a DER certificate and decode it into a certificate structure
*/
NSSLOWCERTCertificate *
nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
{
NSSLOWCERTCertificate *cert;
int rv;
/* allocate the certificate structure */
cert = nsslowcert_CreateCert();
if ( !cert ) {
goto loser;
}
/* point to passed in DER data */
cert->derCert = *derSignedCert;
cert->nickname = NULL;
cert->certKey.data = NULL;
cert->referenceCount = 1;
/* decode the certificate info */
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
&cert->validity, &cert->derSubjKeyInfo, &cert->extensions);
/* cert->subjectKeyID; x509v3 subject key identifier */
cert->subjectKeyID.data = NULL;
cert->subjectKeyID.len = 0;
cert->dbEntry = NULL;
cert ->trust = NULL;
cert ->dbhandle = NULL;
/* generate and save the database key for the cert */
rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
sizeof(cert->certKeySpace), &cert->derIssuer,
&cert->serialNumber, &cert->certKey);
if ( rv ) {
goto loser;
}
/* set the nickname */
if ( nickname == NULL ) {
cert->nickname = NULL;
} else {
/* copy and install the nickname */
cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
sizeof(cert->nicknameSpace));
}
#ifdef FIXME
/* initialize the subjectKeyID */
rv = cert_GetKeyID(cert);
if ( rv != SECSuccess ) {
goto loser;
}
#endif
/* set the email address */
cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);
cert->referenceCount = 1;
return(cert);
loser:
if (cert) {
nsslowcert_DestroyCertificate(cert);
}
return(0);
}
char *
nsslowcert_FixupEmailAddr(char *emailAddr)
{
char *retaddr;
char *str;
if ( emailAddr == NULL ) {
return(NULL);
}
/* copy the string */
str = retaddr = PORT_Strdup(emailAddr);
if ( str == NULL ) {
return(NULL);
}
/* make it lower case */
while ( *str ) {
*str = tolower( *str );
str++;
}
return(retaddr);
}
/*
* Generate a database key, based on serial number and issuer, from a
* DER certificate.
*/
SECStatus
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
{
int rv;
NSSLOWCERTCertKey certkey;
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL,
NULL, NULL, NULL);
if ( rv ) {
goto loser;
}
return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
&certkey.serialNumber, key));
loser:
return(SECFailure);
}
NSSLOWKEYPublicKey *
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
{
NSSLOWCERTSubjectPublicKeyInfo spki;
NSSLOWKEYPublicKey *pubk;
SECItem os;
SECStatus rv;
PRArenaPool *arena;
SECOidTag tag;
SECItem newDerSubjKeyInfo;
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
return NULL;
pubk = (NSSLOWKEYPublicKey *)
PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
if (pubk == NULL) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
pubk->arena = arena;
PORT_Memset(&spki,0,sizeof(spki));
/* copy the DER into the arena, since Quick DER returns data that points
into the DER input, which may get freed by the caller */
rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
if ( rv != SECSuccess ) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
/* we haven't bothered decoding the spki struct yet, do it now */
rv = SEC_QuickDERDecodeItem(arena, &spki,
nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
if (rv != SECSuccess) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
/* Convert bit string length from bits to bytes */
os = spki.subjectPublicKey;
DER_ConvertBitString (&os);
tag = SECOID_GetAlgorithmTag(&spki.algorithm);
switch ( tag ) {
case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION:
pubk->keyType = NSSLOWKEYRSAKey;
prepare_low_rsa_pub_key_for_asn1(pubk);
rv = SEC_QuickDERDecodeItem(arena, pubk,
nsslowcert_RSAPublicKeyTemplate, &os);
if (rv == SECSuccess)
return pubk;
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
pubk->keyType = NSSLOWKEYDSAKey;
prepare_low_dsa_pub_key_for_asn1(pubk);
rv = SEC_QuickDERDecodeItem(arena, pubk,
nsslowcert_DSAPublicKeyTemplate, &os);
if (rv == SECSuccess) return pubk;
break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
pubk->keyType = NSSLOWKEYDHKey;
prepare_low_dh_pub_key_for_asn1(pubk);
rv = SEC_QuickDERDecodeItem(arena, pubk,
nsslowcert_DHPublicKeyTemplate, &os);
if (rv == SECSuccess) return pubk;
break;
#ifdef NSS_ENABLE_ECC
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
pubk->keyType = NSSLOWKEYECKey;
/* Since PKCS#11 directly takes the DER encoding of EC params
* and public value, we don't need any decoding here.
*/
rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding,
&spki.algorithm.parameters);
if ( rv != SECSuccess )
break;
/* Fill out the rest of the ecParams structure
* based on the encoded params
*/
if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
&pubk->u.ec.ecParams) != SECSuccess)
break;
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
if (rv == SECSuccess) return pubk;
break;
#endif /* NSS_ENABLE_ECC */
default:
rv = SECFailure;
break;
}
nsslowkey_DestroyPublicKey (pubk);
return NULL;
}

View File

@@ -1,462 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 ***** */
#include "lowkeyi.h"
#include "secoid.h"
#include "secitem.h"
#include "secder.h"
#include "secasn1.h"
#include "secerr.h"
static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(NSSLOWKEYAttribute) },
{ SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
{ SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue),
SEC_AnyTemplate },
{ 0 }
};
static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
{ SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
};
/* ASN1 Templates for new decoder/encoder */
const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
{ SEC_ASN1_INTEGER,
offsetof(NSSLOWKEYPrivateKeyInfo,version) },
{ SEC_ASN1_INLINE,
offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
SECOID_AlgorithmIDTemplate },
{ SEC_ASN1_OCTET_STRING,
offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
nsslowkey_SetOfAttributeTemplate },
{ 0 }
};
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
{ 0, }
};
const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
{ 0 }
};
const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
{ 0, }
};
const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
};
const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
{ 0, }
};
#ifdef NSS_ENABLE_ECC
/* XXX This is just a placeholder for later when we support
* generic curves and need full-blown support for parsing EC
* parameters. For now, we only support named curves in which
* EC params are simply encoded as an object ID and we don't
* use nsslowkey_ECParamsTemplate.
*/
const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
{ SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
{ SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
{ 0, }
};
/* NOTE: The SECG specification allows the private key structure
* to contain curve parameters but recommends that they be stored
* in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
* instead.
*/
const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
{ SEC_ASN1_OCTET_STRING,
offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
/* XXX The following template works for now since we only
* support named curves for which the parameters are
* encoded as an object ID. When we support generic curves,
* we'll need to define nsslowkey_ECParamsTemplate
*/
#if 1
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
SEC_ObjectIDTemplate },
#else
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
nsslowkey_ECParamsTemplate },
#endif
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1,
offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
SEC_BitStringTemplate },
{ 0, }
};
/*
* smaller version of EC_FillParams. In this code, we only need
* oid and DER data.
*/
SECStatus
LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
ECParams *params)
{
SECOidTag tag;
SECItem oid = { siBuffer, NULL, 0};
#if EC_DEBUG
int i;
printf("Encoded params in EC_DecodeParams: ");
for (i = 0; i < encodedParams->len; i++) {
printf("%02x:", encodedParams->data[i]);
}
printf("\n");
#endif
oid.len = encodedParams->len - 2;
oid.data = encodedParams->data + 2;
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
params->arena = arena;
/* For named curves, fill out curveOID */
params->curveOID.len = oid.len;
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
if (params->curveOID.data == NULL) {
return SECFailure;
}
memcpy(params->curveOID.data, oid.data, oid.len);
return SECSuccess;
}
/* Copy all of the fields from srcParams into dstParams
*/
SECStatus
LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams)
{
SECStatus rv = SECFailure;
dstParams->arena = arena;
rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
&srcParams->DEREncoding);
if (rv != SECSuccess) {
goto loser;
}
rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
&srcParams->curveOID);
if (rv != SECSuccess) {
goto loser;
}
return SECSuccess;
loser:
return SECFailure;
}
#endif /* NSS_ENABLE_ECC */
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
void
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.rsa.modulus.type = siUnsignedInteger;
key->u.rsa.publicExponent.type = siUnsignedInteger;
key->u.rsa.privateExponent.type = siUnsignedInteger;
key->u.rsa.prime1.type = siUnsignedInteger;
key->u.rsa.prime2.type = siUnsignedInteger;
key->u.rsa.exponent1.type = siUnsignedInteger;
key->u.rsa.exponent2.type = siUnsignedInteger;
key->u.rsa.coefficient.type = siUnsignedInteger;
}
void
prepare_low_pqg_params_for_asn1(PQGParams *params)
{
params->prime.type = siUnsignedInteger;
params->subPrime.type = siUnsignedInteger;
params->base.type = siUnsignedInteger;
}
void
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dsa.publicValue.type = siUnsignedInteger;
key->u.dsa.privateValue.type = siUnsignedInteger;
key->u.dsa.params.prime.type = siUnsignedInteger;
key->u.dsa.params.subPrime.type = siUnsignedInteger;
key->u.dsa.params.base.type = siUnsignedInteger;
}
void
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dsa.privateValue.type = siUnsignedInteger;
}
void
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dh.prime.type = siUnsignedInteger;
key->u.dh.base.type = siUnsignedInteger;
key->u.dh.publicValue.type = siUnsignedInteger;
key->u.dh.privateValue.type = siUnsignedInteger;
}
#ifdef NSS_ENABLE_ECC
void
prepare_low_ecparams_for_asn1(ECParams *params)
{
params->DEREncoding.type = siUnsignedInteger;
params->curveOID.type = siUnsignedInteger;
}
void
prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.ec.version.type = siUnsignedInteger;
key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
key->u.ec.privateValue.type = siUnsignedInteger;
key->u.ec.publicValue.type = siUnsignedInteger;
}
#endif /* NSS_ENABLE_ECC */
void
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
{
if (privk && privk->arena) {
PORT_FreeArena(privk->arena, PR_TRUE);
}
}
void
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
{
if (pubk && pubk->arena) {
PORT_FreeArena(pubk->arena, PR_FALSE);
}
}
unsigned
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
{
unsigned char b0;
/* interpret modulus length as key strength... in
* fortezza that's the public key length */
switch (pubk->keyType) {
case NSSLOWKEYRSAKey:
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
default:
break;
}
return 0;
}
unsigned
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
{
unsigned char b0;
switch (privk->keyType) {
case NSSLOWKEYRSAKey:
b0 = privk->u.rsa.modulus.data[0];
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
default:
break;
}
return 0;
}
NSSLOWKEYPublicKey *
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
{
NSSLOWKEYPublicKey *pubk;
PLArenaPool *arena;
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PORT_SetError (SEC_ERROR_NO_MEMORY);
return NULL;
}
switch(privk->keyType) {
case NSSLOWKEYRSAKey:
case NSSLOWKEYNullKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof (NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
if (privk->keyType == NSSLOWKEYNullKey) return pubk;
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
&privk->u.rsa.modulus);
if (rv == SECSuccess) {
rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
&privk->u.rsa.publicExponent);
if (rv == SECSuccess)
return pubk;
}
} else {
PORT_SetError (SEC_ERROR_NO_MEMORY);
}
break;
case NSSLOWKEYDSAKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
&privk->u.dsa.publicValue);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
&privk->u.dsa.params.prime);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
&privk->u.dsa.params.subPrime);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
&privk->u.dsa.params.base);
if (rv == SECSuccess) return pubk;
}
break;
case NSSLOWKEYDHKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
&privk->u.dh.publicValue);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
&privk->u.dh.prime);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
&privk->u.dh.base);
if (rv == SECSuccess) return pubk;
}
break;
#ifdef NSS_ENABLE_ECC
case NSSLOWKEYECKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
&privk->u.ec.publicValue);
if (rv != SECSuccess) break;
pubk->u.ec.ecParams.arena = arena;
/* Copy the rest of the params */
rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
&(privk->u.ec.ecParams));
if (rv == SECSuccess) return pubk;
}
break;
#endif /* NSS_ENABLE_ECC */
/* No Fortezza in Low Key implementations (Fortezza keys aren't
* stored in our data base */
default:
break;
}
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}

View File

@@ -1,198 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 ***** */
/* $Id: lowkeyi.h,v 1.1.2.1 2007-04-03 22:50:02 rrelyea%redhat.com Exp $ */
#ifndef _LOWKEYI_H_
#define _LOWKEYI_H_
#include "prtypes.h"
#include "seccomon.h"
#include "secoidt.h"
#include "pcertt.h"
#include "lowkeyti.h"
#include "sdb.h"
SEC_BEGIN_PROTOS
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
#ifdef NSS_ENABLE_ECC
extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_ecparams_for_asn1(ECParams *params);
#endif /* NSS_ENABLE_ECC */
typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
/*
** Open a key database.
*/
extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
const char *domain,
const char *prefix,
NSSLOWKEYDBNameFunc namecb,
void *cbarg);
/*
** Close the specified key database.
*/
extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
/*
* Get the version number of the database
*/
extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
/*
** Delete a key from the database
*/
extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
const SECItem *pubkey);
/*
** Store a key in the database, indexed by its public key modulus.
** "pk" is the private key to store
** "f" is a the callback function for getting the password
** "arg" is the argument for the callback
*/
extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *pk,
SECItem *pubKeyData,
char *nickname,
SDB *sdb);
/* does the key for this cert exist in the database filed by modulus */
extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
NSSLOWCERTCertificate *cert);
/* does a key with this ID already exist? */
extern PRBool nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id);
/*
** Destroy a private key object.
** "key" the object
** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key);
/*
** Destroy a public key object.
** "key" the object
** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
/*
** Return the modulus length of "pubKey".
*/
extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
/*
** Return the modulus length of "privKey".
*/
extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
/*
** Convert a low private key "privateKey" into a public low key
*/
extern NSSLOWKEYPublicKey
*nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
SECStatus
nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
SDB *sdb);
/* Store key by modulus and specify an encryption algorithm to use.
* handle is the pointer to the key database,
* privkey is the private key to be stored,
* f and arg are the function and arguments to the callback
* to get a password,
* algorithm is the algorithm which the privKey is to be stored.
* A return of anything but SECSuccess indicates failure.
*/
extern SECStatus
nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
SDB *sdb,
PRBool update);
/* Find key by modulus. This function is the inverse of store key
* by modulus. An attempt to locate the key with "modulus" is
* performed. If the key is found, the private key is returned,
* else NULL is returned.
* modulus is the modulus to locate
*/
extern NSSLOWKEYPrivateKey *
nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
SDB *sdb);
extern char *
nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
SECItem *modulus, SDB *sdb);
#ifdef NSS_ENABLE_ECC
/*
* smaller version of EC_FillParams. In this code, we only need
* oid and DER data.
*/
SECStatus LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
ECParams *params);
/* Copy all of the fields from srcParams into dstParams */
SECStatus LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams);
#endif
SEC_END_PROTOS
#endif /* _LOWKEYI_H_ */

View File

@@ -1,161 +0,0 @@
/* ***** 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):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* 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 _LOWKEYTI_H_
#define _LOWKEYTI_H_ 1
#include "blapit.h"
#include "prtypes.h"
#include "plarena.h"
#include "secitem.h"
#include "secasn1t.h"
#include "secoidt.h"
/*
* a key in/for the data base
*/
struct NSSLOWKEYDBKeyStr {
PLArenaPool *arena;
int version;
char *nickname;
SECItem salt;
SECItem derPK;
};
typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey;
typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle;
#ifdef NSS_USE_KEY4_DB
#define NSSLOWKEY_DB_FILE_VERSION 4
#else
#define NSSLOWKEY_DB_FILE_VERSION 3
#endif
#define NSSLOWKEY_VERSION 0 /* what we *create* */
/*
** Typedef for callback to get a password "key".
*/
extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[];
#ifdef NSS_ENABLE_ECC
#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */
extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[];
extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[];
#endif /* NSS_ENABLE_ECC */
extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
/*
* PKCS #8 attributes
*/
struct NSSLOWKEYAttributeStr {
SECItem attrType;
SECItem *attrValue;
};
typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute;
/*
** A PKCS#8 private key info object
*/
struct NSSLOWKEYPrivateKeyInfoStr {
PLArenaPool *arena;
SECItem version;
SECAlgorithmID algorithm;
SECItem privateKey;
NSSLOWKEYAttribute **attributes;
};
typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
/*
** A PKCS#8 private key info object
*/
struct NSSLOWKEYEncryptedPrivateKeyInfoStr {
PLArenaPool *arena;
SECAlgorithmID algorithm;
SECItem encryptedData;
};
typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo;
typedef enum {
NSSLOWKEYNullKey = 0,
NSSLOWKEYRSAKey = 1,
NSSLOWKEYDSAKey = 2,
NSSLOWKEYDHKey = 4,
NSSLOWKEYECKey = 5
} NSSLOWKEYType;
/*
** An RSA public key object.
*/
struct NSSLOWKEYPublicKeyStr {
PLArenaPool *arena;
NSSLOWKEYType keyType ;
union {
RSAPublicKey rsa;
DSAPublicKey dsa;
DHPublicKey dh;
ECPublicKey ec;
} u;
};
typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey;
/*
** Low Level private key object
** This is only used by the raw Crypto engines (crypto), keydb (keydb),
** and PKCS #11. Everyone else uses the high level key structure.
*/
struct NSSLOWKEYPrivateKeyStr {
PLArenaPool *arena;
NSSLOWKEYType keyType;
union {
RSAPrivateKey rsa;
DSAPrivateKey dsa;
DHPrivateKey dh;
ECPrivateKey ec;
} u;
};
typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
#endif /* _LOWKEYTI_H_ */

View File

@@ -1,68 +0,0 @@
#
# ***** 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 *****
CORE_DEPTH = ../../../..
MODULE = nss
REQUIRES = dbm
LIBRARY_NAME = lgdbm
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/lgdbm.def
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
CSRCS = \
dbmshim.c \
keydb.c \
lgattr.c \
lgcreate.c \
lgdestroy.c \
lgfind.c \
lginit.c \
lgutil.c \
lowcert.c \
lowkey.c \
pcertdb.c \
pk11db.c \
$(NULL)
ifdef NSS_ENABLE_ECC
DEFINES += -DNSS_ENABLE_ECC
endif

View File

@@ -1,261 +0,0 @@
/* ***** 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 _PCERTDB_H_
#define _PCERTDB_H_
#include "plarena.h"
#include "prlong.h"
#include "pcertt.h"
#include "lowkeyti.h" /* for struct NSSLOWKEYPublicKeyStr */
SEC_BEGIN_PROTOS
/*
* initialize any global certificate locks
*/
SECStatus nsslowcert_InitLocks(void);
/*
** Add a DER encoded certificate to the permanent database.
** "derCert" is the DER encoded certificate.
** "nickname" is the nickname to use for the cert
** "trust" is the trust parameters for the cert
*/
SECStatus nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *handle,
NSSLOWCERTCertificate *cert,
char *nickname, NSSLOWCERTCertTrust *trust);
SECStatus nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle,
NSSLOWCERTCertificate *cert, char *nickname);
SECStatus nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert);
typedef SECStatus (PR_CALLBACK * PermCertCallback)(NSSLOWCERTCertificate *cert,
SECItem *k, void *pdata);
/*
** Traverse the entire permanent database, and pass the certs off to a
** user supplied function.
** "certfunc" is the user function to call for each certificate
** "udata" is the user's data, which is passed through to "certfunc"
*/
SECStatus
nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle,
PermCertCallback certfunc,
void *udata );
PRBool
nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle);
certDBEntryRevocation *
nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle,
SECItem *crlKey, PRBool isKRL);
SECStatus
nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,const SECItem *derName,
PRBool isKRL);
SECStatus
nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl ,
SECItem *derKey, char *url, PRBool isKRL);
NSSLOWCERTCertDBHandle *nsslowcert_GetDefaultCertDB();
NSSLOWKEYPublicKey *nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *);
NSSLOWCERTCertificate *
nsslowcert_NewTempCertificate(NSSLOWCERTCertDBHandle *handle, SECItem *derCert,
char *nickname, PRBool isperm, PRBool copyDER);
NSSLOWCERTCertificate *
nsslowcert_DupCertificate(NSSLOWCERTCertificate *cert);
void nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert);
void nsslowcert_DestroyTrust(NSSLOWCERTTrust *Trust);
/*
* Lookup a certificate in the databases without locking
* "certKey" is the database key to look for
*
* XXX - this should be internal, but pkcs 11 needs to call it during a
* traversal.
*/
NSSLOWCERTCertificate *
nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey);
/*
* Lookup trust for a certificate in the databases without locking
* "certKey" is the database key to look for
*
* XXX - this should be internal, but pkcs 11 needs to call it during a
* traversal.
*/
NSSLOWCERTTrust *
nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, const SECItem *certKey);
/*
** Generate a certificate key from the issuer and serialnumber, then look it
** up in the database. Return the cert if found.
** "issuerAndSN" is the issuer and serial number to look for
*/
extern NSSLOWCERTCertificate *
nsslowcert_FindCertByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
/*
** Generate a certificate key from the issuer and serialnumber, then look it
** up in the database. Return the cert if found.
** "issuerAndSN" is the issuer and serial number to look for
*/
extern NSSLOWCERTTrust *
nsslowcert_FindTrustByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
/*
** Find a certificate in the database by a DER encoded certificate
** "derCert" is the DER encoded certificate
*/
extern NSSLOWCERTCertificate *
nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert);
/* convert an email address to lower case */
char *nsslowcert_FixupEmailAddr(char *emailAddr);
/*
** Decode a DER encoded certificate into an NSSLOWCERTCertificate structure
** "derSignedCert" is the DER encoded signed certificate
** "copyDER" is true if the DER should be copied, false if the
** existing copy should be referenced
** "nickname" is the nickname to use in the database. If it is NULL
** then a temporary nickname is generated.
*/
extern NSSLOWCERTCertificate *
nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, char *nickname);
SECStatus
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key);
certDBEntrySMime *
nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *certHandle,
char *emailAddr);
void
nsslowcert_DestroyDBEntry(certDBEntry *entry);
SECStatus
nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
const char *domain, const char *prefix,
NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile);
void
nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle);
/*
* is certa newer than certb? If one is expired, pick the other one.
*/
PRBool
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb);
SECStatus
nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
certDBEntryType type,
SECStatus (* callback)(SECItem *data, SECItem *key,
certDBEntryType type, void *pdata),
void *udata );
SECStatus
nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
SECItem *derSubject,
NSSLOWCERTCertCallback cb, void *cbarg);
int
nsslowcert_NumPermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
SECItem *derSubject);
SECStatus
nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
char *nickname, NSSLOWCERTCertCallback cb, void *cbarg);
int
nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
char *nickname);
SECStatus
nsslowcert_GetCertTrust(NSSLOWCERTCertificate *cert,
NSSLOWCERTCertTrust *trust);
SECStatus
nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr,
SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime);
/*
* Change the trust attributes of a certificate and make them permanent
* in the database.
*/
SECStatus
nsslowcert_ChangeCertTrust(NSSLOWCERTCertDBHandle *handle,
NSSLOWCERTCertificate *cert, NSSLOWCERTCertTrust *trust);
PRBool
nsslowcert_needDBVerify(NSSLOWCERTCertDBHandle *handle);
void
nsslowcert_setDBVerify(NSSLOWCERTCertDBHandle *handle, PRBool value);
PRBool
nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust);
void
nsslowcert_DestroyFreeLists(void);
void
nsslowcert_DestroyGlobalLocks(void);
void
pkcs11_freeNickname(char *nickname, char *space);
char *
pkcs11_copyNickname(char *nickname, char *space, int spaceLen);
void
pkcs11_freeStaticData(unsigned char *data, unsigned char *space);
unsigned char *
pkcs11_allocStaticData(int datalen, unsigned char *space, int spaceLen);
unsigned char *
pkcs11_copyStaticData(unsigned char *data, int datalen, unsigned char *space,
int spaceLen);
NSSLOWCERTCertificate *
nsslowcert_CreateCert(void);
certDBEntry *
nsslowcert_DecodeAnyDBEntry(SECItem *dbData, const SECItem *dbKey,
certDBEntryType entryType, void *pdata);
SEC_END_PROTOS
#endif /* _PCERTDB_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,450 +0,0 @@
/* ***** 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 ***** */
/*
* certt.h - public data structures for the certificate library
*
* $Id: pcertt.h,v 1.1.2.2 2007-05-15 21:59:52 rrelyea%redhat.com Exp $
*/
#ifndef _PCERTT_H_
#define _PCERTT_H_
#include "prclist.h"
#include "pkcs11t.h"
#include "seccomon.h"
#include "secoidt.h"
#include "plarena.h"
#include "prcvar.h"
#include "nssilock.h"
#include "prio.h"
#include "prmon.h"
/* Non-opaque objects */
typedef struct NSSLOWCERTCertDBHandleStr NSSLOWCERTCertDBHandle;
typedef struct NSSLOWCERTCertKeyStr NSSLOWCERTCertKey;
typedef struct NSSLOWCERTTrustStr NSSLOWCERTTrust;
typedef struct NSSLOWCERTCertTrustStr NSSLOWCERTCertTrust;
typedef struct NSSLOWCERTCertificateStr NSSLOWCERTCertificate;
typedef struct NSSLOWCERTCertificateListStr NSSLOWCERTCertificateList;
typedef struct NSSLOWCERTIssuerAndSNStr NSSLOWCERTIssuerAndSN;
typedef struct NSSLOWCERTSignedDataStr NSSLOWCERTSignedData;
typedef struct NSSLOWCERTSubjectPublicKeyInfoStr NSSLOWCERTSubjectPublicKeyInfo;
typedef struct NSSLOWCERTValidityStr NSSLOWCERTValidity;
/*
** An X.509 validity object
*/
struct NSSLOWCERTValidityStr {
PRArenaPool *arena;
SECItem notBefore;
SECItem notAfter;
};
/*
* A serial number and issuer name, which is used as a database key
*/
struct NSSLOWCERTCertKeyStr {
SECItem serialNumber;
SECItem derIssuer;
};
/*
** A signed data object. Used to implement the "signed" macro used
** in the X.500 specs.
*/
struct NSSLOWCERTSignedDataStr {
SECItem data;
SECAlgorithmID signatureAlgorithm;
SECItem signature;
};
/*
** An X.509 subject-public-key-info object
*/
struct NSSLOWCERTSubjectPublicKeyInfoStr {
PRArenaPool *arena;
SECAlgorithmID algorithm;
SECItem subjectPublicKey;
};
typedef struct _certDBEntryCert certDBEntryCert;
typedef struct _certDBEntryRevocation certDBEntryRevocation;
struct NSSLOWCERTCertTrustStr {
unsigned int sslFlags;
unsigned int emailFlags;
unsigned int objectSigningFlags;
};
/*
** PKCS11 Trust representation
*/
struct NSSLOWCERTTrustStr {
NSSLOWCERTTrust *next;
NSSLOWCERTCertDBHandle *dbhandle;
SECItem dbKey; /* database key for this cert */
certDBEntryCert *dbEntry; /* database entry struct */
NSSLOWCERTCertTrust *trust;
SECItem *derCert; /* original DER for the cert */
unsigned char dbKeySpace[512];
};
/*
** An X.509 certificate object (the unsigned form)
*/
struct NSSLOWCERTCertificateStr {
/* the arena is used to allocate any data structures that have the same
* lifetime as the cert. This is all stuff that hangs off of the cert
* structure, and is all freed at the same time. I is used when the
* cert is decoded, destroyed, and at some times when it changes
* state
*/
NSSLOWCERTCertificate *next;
NSSLOWCERTCertDBHandle *dbhandle;
SECItem derCert; /* original DER for the cert */
SECItem derIssuer; /* DER for issuer name */
SECItem derSN;
SECItem serialNumber;
SECItem derSubject; /* DER for subject name */
SECItem derSubjKeyInfo;
NSSLOWCERTSubjectPublicKeyInfo *subjectPublicKeyInfo;
SECItem certKey; /* database key for this cert */
SECItem validity;
certDBEntryCert *dbEntry; /* database entry struct */
SECItem subjectKeyID; /* x509v3 subject key identifier */
SECItem extensions;
char *nickname;
char *emailAddr;
NSSLOWCERTCertTrust *trust;
/* the reference count is modified whenever someone looks up, dups
* or destroys a certificate
*/
int referenceCount;
char nicknameSpace[200];
char emailAddrSpace[200];
unsigned char certKeySpace[512];
};
#define SEC_CERTIFICATE_VERSION_1 0 /* default created */
#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */
#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */
#define SEC_CRL_VERSION_1 0 /* default */
#define SEC_CRL_VERSION_2 1 /* v2 extensions */
struct NSSLOWCERTIssuerAndSNStr {
SECItem derIssuer;
SECItem serialNumber;
};
typedef SECStatus (* NSSLOWCERTCertCallback)(NSSLOWCERTCertificate *cert, void *arg);
/* This is the typedef for the callback passed to nsslowcert_OpenCertDB() */
/* callback to return database name based on version number */
typedef char * (*NSSLOWCERTDBNameFunc)(void *arg, int dbVersion);
/* XXX Lisa thinks the template declarations belong in cert.h, not here? */
#include "secasn1t.h" /* way down here because I expect template stuff to
* move out of here anyway */
/*
* Certificate Database related definitions and data structures
*/
/* version number of certificate database */
#define CERT_DB_FILE_VERSION 8
#define CERT_DB_V7_FILE_VERSION 7
#define CERT_DB_CONTENT_VERSION 2
#define SEC_DB_ENTRY_HEADER_LEN 3
#define SEC_DB_KEY_HEADER_LEN 1
/* All database entries have this form:
*
* byte offset field
* ----------- -----
* 0 version
* 1 type
* 2 flags
*/
/* database entry types */
typedef enum {
certDBEntryTypeVersion = 0,
certDBEntryTypeCert = 1,
certDBEntryTypeNickname = 2,
certDBEntryTypeSubject = 3,
certDBEntryTypeRevocation = 4,
certDBEntryTypeKeyRevocation = 5,
certDBEntryTypeSMimeProfile = 6,
certDBEntryTypeContentVersion = 7,
certDBEntryTypeBlob = 8
} certDBEntryType;
typedef struct {
certDBEntryType type;
unsigned int version;
unsigned int flags;
PRArenaPool *arena;
} certDBEntryCommon;
/*
* Certificate entry:
*
* byte offset field
* ----------- -----
* 0 sslFlags-msb
* 1 sslFlags-lsb
* 2 emailFlags-msb
* 3 emailFlags-lsb
* 4 objectSigningFlags-msb
* 5 objectSigningFlags-lsb
* 6 derCert-len-msb
* 7 derCert-len-lsb
* 8 nickname-len-msb
* 9 nickname-len-lsb
* ... derCert
* ... nickname
*
* NOTE: the nickname string as stored in the database is null terminated,
* in other words, the last byte of the db entry is always 0
* if a nickname is present.
* NOTE: if nickname is not present, then nickname-len-msb and
* nickname-len-lsb will both be zero.
*/
struct _certDBEntryCert {
certDBEntryCommon common;
certDBEntryCert *next;
NSSLOWCERTCertTrust trust;
SECItem derCert;
char *nickname;
char nicknameSpace[200];
unsigned char derCertSpace[2048];
};
/*
* Certificate Nickname entry:
*
* byte offset field
* ----------- -----
* 0 subjectname-len-msb
* 1 subjectname-len-lsb
* 2... subjectname
*
* The database key for this type of entry is a nickname string
* The "subjectname" value is the DER encoded DN of the identity
* that matches this nickname.
*/
typedef struct {
certDBEntryCommon common;
char *nickname;
SECItem subjectName;
} certDBEntryNickname;
#define DB_NICKNAME_ENTRY_HEADER_LEN 2
/*
* Certificate Subject entry:
*
* byte offset field
* ----------- -----
* 0 ncerts-msb
* 1 ncerts-lsb
* 2 nickname-msb
* 3 nickname-lsb
* 4 emailAddr-msb
* 5 emailAddr-lsb
* ... nickname
* ... emailAddr
* ...+2*i certkey-len-msb
* ...+1+2*i certkey-len-lsb
* ...+2*ncerts+2*i keyid-len-msb
* ...+1+2*ncerts+2*i keyid-len-lsb
* ... certkeys
* ... keyids
*
* The database key for this type of entry is the DER encoded subject name
* The "certkey" value is an array of certificate database lookup keys that
* points to the database entries for the certificates that matche
* this subject.
*
*/
typedef struct _certDBEntrySubject {
certDBEntryCommon common;
SECItem derSubject;
unsigned int ncerts;
char *nickname;
SECItem *certKeys;
SECItem *keyIDs;
char **emailAddrs;
unsigned int nemailAddrs;
} certDBEntrySubject;
#define DB_SUBJECT_ENTRY_HEADER_LEN 6
/*
* Certificate SMIME profile entry:
*
* byte offset field
* ----------- -----
* 0 subjectname-len-msb
* 1 subjectname-len-lsb
* 2 smimeoptions-len-msb
* 3 smimeoptions-len-lsb
* 4 options-date-len-msb
* 5 options-date-len-lsb
* 6... subjectname
* ... smimeoptions
* ... options-date
*
* The database key for this type of entry is the email address string
* The "subjectname" value is the DER encoded DN of the identity
* that matches this nickname.
* The "smimeoptions" value is a string that represents the algorithm
* capabilities on the remote user.
* The "options-date" is the date that the smime options value was created.
* This is generally the signing time of the signed message that contained
* the options. It is a UTCTime value.
*/
typedef struct {
certDBEntryCommon common;
char *emailAddr;
SECItem subjectName;
SECItem smimeOptions;
SECItem optionsDate;
} certDBEntrySMime;
#define DB_SMIME_ENTRY_HEADER_LEN 6
/*
* Crl/krl entry:
*
* byte offset field
* ----------- -----
* 0 derCert-len-msb
* 1 derCert-len-lsb
* 2 url-len-msb
* 3 url-len-lsb
* ... derCert
* ... url
*
* NOTE: the url string as stored in the database is null terminated,
* in other words, the last byte of the db entry is always 0
* if a nickname is present.
* NOTE: if url is not present, then url-len-msb and
* url-len-lsb will both be zero.
*/
#define DB_CRL_ENTRY_HEADER_LEN 4
struct _certDBEntryRevocation {
certDBEntryCommon common;
SECItem derCrl;
char *url; /* where to load the crl from */
};
/*
* Database Version Entry:
*
* byte offset field
* ----------- -----
* only the low level header...
*
* The database key for this type of entry is the string "Version"
*/
typedef struct {
certDBEntryCommon common;
} certDBEntryVersion;
#define SEC_DB_VERSION_KEY "Version"
#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY)
/*
* Database Content Version Entry:
*
* byte offset field
* ----------- -----
* 0 contentVersion
*
* The database key for this type of entry is the string "ContentVersion"
*/
typedef struct {
certDBEntryCommon common;
char contentVersion;
} certDBEntryContentVersion;
#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion"
#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY)
typedef union {
certDBEntryCommon common;
certDBEntryCert cert;
certDBEntryContentVersion content;
certDBEntryNickname nickname;
certDBEntryRevocation revocation;
certDBEntrySMime smime;
certDBEntrySubject subject;
certDBEntryVersion version;
} certDBEntry;
/* length of the fixed part of a database entry */
#define DBCERT_V4_HEADER_LEN 7
#define DB_CERT_V5_ENTRY_HEADER_LEN 7
#define DB_CERT_V6_ENTRY_HEADER_LEN 7
#define DB_CERT_ENTRY_HEADER_LEN 10
/* common flags for all types of certificates */
#define CERTDB_VALID_PEER (1<<0)
#define CERTDB_TRUSTED (1<<1)
#define CERTDB_SEND_WARN (1<<2)
#define CERTDB_VALID_CA (1<<3)
#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */
#define CERTDB_NS_TRUSTED_CA (1<<5)
#define CERTDB_USER (1<<6)
#define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */
#define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */
#define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */
#define CERTDB_NOT_TRUSTED (1<<10) /* explicitly don't trust this cert */
#define CERTDB_TRUSTED_UNKNOWN (1<<11) /* accept trust from another source */
/* bits not affected by the CKO_NETSCAPE_TRUST object */
#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER | CERTDB_VALID_PEER | \
CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \
CERTDB_GOVT_APPROVED_CA)
#endif /* _PCERTT_H_ */

View File

@@ -1,773 +0,0 @@
/* ***** 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 ***** */
/*
* The following code handles the storage of PKCS 11 modules used by the
* NSS. This file is written to abstract away how the modules are
* stored so we can deside that later.
*/
#include "pk11pars.h"
#include "lgdb.h"
#include "mcom_db.h"
#include "secerr.h"
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
/* Construct a database key for a given module */
static SECStatus secmod_MakeKey(DBT *key, char * module) {
int len = 0;
char *commonName;
commonName = secmod_argGetParamValue("name",module);
if (commonName == NULL) {
commonName = secmod_argGetParamValue("library",module);
}
if (commonName == NULL) return SECFailure;
len = PORT_Strlen(commonName);
key->data = commonName;
key->size = len;
return SECSuccess;
}
/* free out constructed database key */
static void
secmod_FreeKey(DBT *key)
{
if (key->data) {
PORT_Free(key->data);
}
key->data = NULL;
key->size = 0;
}
typedef struct secmodDataStr secmodData;
typedef struct secmodSlotDataStr secmodSlotData;
struct secmodDataStr {
unsigned char major;
unsigned char minor;
unsigned char nameStart[2];
unsigned char slotOffset[2];
unsigned char internal;
unsigned char fips;
unsigned char ssl[8];
unsigned char trustOrder[4];
unsigned char cipherOrder[4];
unsigned char reserved1;
unsigned char isModuleDB;
unsigned char isModuleDBOnly;
unsigned char isCritical;
unsigned char reserved[4];
unsigned char names[6]; /* enough space for the length fields */
};
struct secmodSlotDataStr {
unsigned char slotID[4];
unsigned char defaultFlags[4];
unsigned char timeout[4];
unsigned char askpw;
unsigned char hasRootCerts;
unsigned char reserved[18]; /* this makes it a round 32 bytes */
};
#define SECMOD_DB_VERSION_MAJOR 0
#define SECMOD_DB_VERSION_MINOR 6
#define SECMOD_DB_EXT1_VERSION_MAJOR 0
#define SECMOD_DB_EXT1_VERSION_MINOR 6
#define SECMOD_DB_NOUI_VERSION_MAJOR 0
#define SECMOD_DB_NOUI_VERSION_MINOR 4
#define SECMOD_PUTSHORT(dest,src) \
(dest)[1] = (unsigned char) ((src)&0xff); \
(dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
#define SECMOD_PUTLONG(dest,src) \
(dest)[3] = (unsigned char) ((src)&0xff); \
(dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
(dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
(dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
#define SECMOD_GETSHORT(src) \
((unsigned short) (((src)[0] << 8) | (src)[1]))
#define SECMOD_GETLONG(src) \
((unsigned long) (( (unsigned long) (src)[0] << 24) | \
( (unsigned long) (src)[1] << 16) | \
( (unsigned long) (src)[2] << 8) | \
(unsigned long) (src)[3]))
/*
* build a data base entry from a module
*/
static SECStatus
secmod_EncodeData(DBT *data, char * module)
{
secmodData *encoded = NULL;
secmodSlotData *slot;
unsigned char *dataPtr;
unsigned short len, len2 = 0, len3 = 0;
int count = 0;
unsigned short offset;
int dataLen, i;
unsigned long order;
unsigned long ssl[2];
char *commonName = NULL , *dllName = NULL, *param = NULL, *nss = NULL;
char *slotParams, *ciphers;
PK11PreSlotInfo *slotInfo = NULL;
SECStatus rv = SECFailure;
rv = secmod_argParseModuleSpec(module,&dllName,&commonName,&param,&nss);
if (rv != SECSuccess) return rv;
rv = SECFailure;
if (commonName == NULL) {
/* set error */
goto loser;
}
len = PORT_Strlen(commonName);
if (dllName) {
len2 = PORT_Strlen(dllName);
}
if (param) {
len3 = PORT_Strlen(param);
}
slotParams = secmod_argGetParamValue("slotParams",nss);
slotInfo = secmod_argParseSlotInfo(NULL,slotParams,&count);
if (slotParams) PORT_Free(slotParams);
if (count && slotInfo == NULL) {
/* set error */
goto loser;
}
dataLen = sizeof(secmodData) + len + len2 + len3 + sizeof(unsigned short) +
count*sizeof(secmodSlotData);
data->data = (unsigned char *) PORT_ZAlloc(dataLen);
encoded = (secmodData *)data->data;
dataPtr = (unsigned char *) data->data;
data->size = dataLen;
if (encoded == NULL) {
/* set error */
goto loser;
}
encoded->major = SECMOD_DB_VERSION_MAJOR;
encoded->minor = SECMOD_DB_VERSION_MINOR;
encoded->internal = (unsigned char)
(secmod_argHasFlag("flags","internal",nss) ? 1 : 0);
encoded->fips = (unsigned char)
(secmod_argHasFlag("flags","FIPS",nss) ? 1 : 0);
encoded->isModuleDB = (unsigned char)
(secmod_argHasFlag("flags","isModuleDB",nss) ? 1 : 0);
encoded->isModuleDBOnly = (unsigned char)
(secmod_argHasFlag("flags","isModuleDBOnly",nss) ? 1 : 0);
encoded->isCritical = (unsigned char)
(secmod_argHasFlag("flags","critical",nss) ? 1 : 0);
order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER,
NULL);
SECMOD_PUTLONG(encoded->trustOrder,order);
order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER,
NULL);
SECMOD_PUTLONG(encoded->cipherOrder,order);
ciphers = secmod_argGetParamValue("ciphers",nss);
secmod_argSetNewCipherFlags(&ssl[0], ciphers);
SECMOD_PUTLONG(encoded->ssl,ssl[0]);
SECMOD_PUTLONG(&encoded->ssl[4],ssl[1]);
if (ciphers) PORT_Free(ciphers);
offset = (unsigned short) &(((secmodData *)0)->names[0]);
SECMOD_PUTSHORT(encoded->nameStart,offset);
offset = offset + len + len2 + len3 + 3*sizeof(unsigned short);
SECMOD_PUTSHORT(encoded->slotOffset,offset);
SECMOD_PUTSHORT(&dataPtr[offset],((unsigned short)count));
slot = (secmodSlotData *)(dataPtr+offset+sizeof(unsigned short));
offset = 0;
SECMOD_PUTSHORT(encoded->names,len);
offset += sizeof(unsigned short);
PORT_Memcpy(&encoded->names[offset],commonName,len);
offset += len;
SECMOD_PUTSHORT(&encoded->names[offset],len2);
offset += sizeof(unsigned short);
if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
offset += len2;
SECMOD_PUTSHORT(&encoded->names[offset],len3);
offset += sizeof(unsigned short);
if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
offset += len3;
if (count) {
for (i=0; i < count; i++) {
SECMOD_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
SECMOD_PUTLONG(slot[i].defaultFlags,
slotInfo[i].defaultFlags);
SECMOD_PUTLONG(slot[i].timeout,slotInfo[i].timeout);
slot[i].askpw = slotInfo[i].askpw;
slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
}
}
rv = SECSuccess;
loser:
if (commonName) PORT_Free(commonName);
if (dllName) PORT_Free(dllName);
if (param) PORT_Free(param);
if (slotInfo) PORT_Free(slotInfo);
if (nss) PORT_Free(nss);
return rv;
}
static void
secmod_FreeData(DBT *data)
{
if (data->data) {
PORT_Free(data->data);
}
}
static void
secmod_FreeSlotStrings(char **slotStrings, int count)
{
int i;
for (i=0; i < count; i++) {
if (slotStrings[i]) {
PR_smprintf_free(slotStrings[i]);
slotStrings[i] = NULL;
}
}
}
/*
* build a module from the data base entry.
*/
static char *
secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
{
secmodData *encoded;
secmodSlotData *slots;
PLArenaPool *arena;
char *commonName = NULL;
char *dllName = NULL;
char *parameters = NULL;
char *nss;
char *moduleSpec;
char **slotStrings = NULL;
unsigned char *names;
unsigned long slotCount;
unsigned long ssl0 =0;
unsigned long ssl1 =0;
unsigned long slotID;
unsigned long defaultFlags;
unsigned long timeout;
unsigned long trustOrder =SECMOD_DEFAULT_TRUST_ORDER;
unsigned long cipherOrder =SECMOD_DEFAULT_CIPHER_ORDER;
unsigned short len;
unsigned short namesOffset = 0; /* start of the names block */
unsigned long namesRunningOffset; /* offset to name we are
* currently processing */
unsigned short slotOffset;
PRBool isOldVersion = PR_FALSE;
PRBool internal;
PRBool isFIPS;
PRBool isModuleDB =PR_FALSE;
PRBool isModuleDBOnly =PR_FALSE;
PRBool extended =PR_FALSE;
int i;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (arena == NULL)
return NULL;
#define CHECK_SIZE(x) \
if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
/* -------------------------------------------------------------
** Process the buffer header, which is the secmodData struct.
** It may be an old or new version. Check the length for each.
*/
CHECK_SIZE( offsetof(secmodData, trustOrder[0]) );
encoded = (secmodData *)data->data;
internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
if (retInternal)
*retInternal = internal;
if (internal) {
parameters = PORT_ArenaStrdup(arena,defParams);
if (parameters == NULL)
goto loser;
}
if (internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
(encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
isOldVersion = PR_TRUE;
}
if ((encoded->major == SECMOD_DB_EXT1_VERSION_MAJOR) &&
(encoded->minor >= SECMOD_DB_EXT1_VERSION_MINOR)) {
CHECK_SIZE( sizeof(secmodData));
trustOrder = SECMOD_GETLONG(encoded->trustOrder);
cipherOrder = SECMOD_GETLONG(encoded->cipherOrder);
isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE: PR_FALSE;
isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE: PR_FALSE;
extended = PR_TRUE;
}
if (internal && !extended) {
trustOrder = 0;
cipherOrder = 100;
}
/* decode SSL cipher enable flags */
ssl0 = SECMOD_GETLONG(encoded->ssl);
ssl1 = SECMOD_GETLONG(encoded->ssl + 4);
slotOffset = SECMOD_GETSHORT(encoded->slotOffset);
namesOffset = SECMOD_GETSHORT(encoded->nameStart);
/*--------------------------------------------------------------
** Now process the variable length set of names.
** The names have this structure:
** struct {
** BYTE commonNameLen[ 2 ];
** BYTE commonName [ commonNameLen ];
** BTTE libNameLen [ 2 ];
** BYTE libName [ libNameLen ];
** If it is "extended" it also has these members:
** BYTE initStringLen[ 2 ];
** BYTE initString [ initStringLen ];
** }
*/
namesRunningOffset = namesOffset;
/* copy the module's common name */
CHECK_SIZE( namesRunningOffset + 2);
names = (unsigned char *)data->data;
len = SECMOD_GETSHORT(names+namesRunningOffset);
CHECK_SIZE( namesRunningOffset + 2 + len);
commonName = (char*)PORT_ArenaAlloc(arena,len+1);
if (commonName == NULL)
goto loser;
PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
commonName[len] = 0;
namesRunningOffset += len + 2;
/* copy the module's shared library file name. */
CHECK_SIZE( namesRunningOffset + 2);
len = SECMOD_GETSHORT(names + namesRunningOffset);
if (len) {
CHECK_SIZE( namesRunningOffset + 2 + len);
dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
if (dllName == NULL)
goto loser;
PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
dllName[len] = 0;
}
namesRunningOffset += len + 2;
/* copy the module's initialization string, if present. */
if (!internal && extended) {
CHECK_SIZE( namesRunningOffset + 2);
len = SECMOD_GETSHORT(names+namesRunningOffset);
if (len) {
CHECK_SIZE( namesRunningOffset + 2 + len );
parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
if (parameters == NULL)
goto loser;
PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
parameters[len] = 0;
}
namesRunningOffset += len + 2;
}
/*
* Consistency check: Make sure the slot and names blocks don't
* overlap. These blocks can occur in any order, so this check is made
* in 2 parts. First we check the case where the slot block starts
* after the name block. Later, when we have the slot block length,
* we check the case where slot block starts before the name block.
* NOTE: in most cases any overlap will likely be detected by invalid
* data read from the blocks, but it's better to find out sooner
* than later.
*/
if (slotOffset >= namesOffset) { /* slot block starts after name block */
if (slotOffset < namesRunningOffset) {
goto db_loser;
}
}
/* ------------------------------------------------------------------
** Part 3, process the slot table.
** This part has this structure:
** struct {
** BYTE slotCount [ 2 ];
** secmodSlotData [ slotCount ];
** {
*/
CHECK_SIZE( slotOffset + 2 );
slotCount = SECMOD_GETSHORT((unsigned char *)data->data + slotOffset);
/*
* Consistency check: Part 2. We now have the slot block length, we can
* check the case where the slotblock procedes the name block.
*/
if (slotOffset < namesOffset) { /* slot block starts before name block */
if (namesOffset < slotOffset + 2 + slotCount*sizeof(secmodSlotData)) {
goto db_loser;
}
}
CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(secmodSlotData)));
slots = (secmodSlotData *) ((unsigned char *)data->data + slotOffset + 2);
/* slotCount; */
slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
if (slotStrings == NULL)
goto loser;
for (i=0; i < (int) slotCount; i++, slots++) {
PRBool hasRootCerts =PR_FALSE;
PRBool hasRootTrust =PR_FALSE;
slotID = SECMOD_GETLONG(slots->slotID);
defaultFlags = SECMOD_GETLONG(slots->defaultFlags);
timeout = SECMOD_GETLONG(slots->timeout);
hasRootCerts = slots->hasRootCerts;
if (isOldVersion && internal && (slotID != 2)) {
unsigned long internalFlags=
secmod_argSlotFlags("slotFlags",SECMOD_SLOT_FLAGS);
defaultFlags |= internalFlags;
}
if (hasRootCerts && !extended) {
trustOrder = 100;
}
slotStrings[i] = secmod_mkSlotString(slotID, defaultFlags, timeout,
(unsigned char)slots->askpw,
hasRootCerts, hasRootTrust);
if (slotStrings[i] == NULL) {
secmod_FreeSlotStrings(slotStrings,i);
goto loser;
}
}
nss = secmod_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB,
isModuleDBOnly, internal, trustOrder, cipherOrder,
ssl0, ssl1);
secmod_FreeSlotStrings(slotStrings,slotCount);
/* it's permissible (and normal) for nss to be NULL. it simply means
* there are no NSS specific parameters in the database */
moduleSpec = secmod_mkNewModuleSpec(dllName,commonName,parameters,nss);
PR_smprintf_free(nss);
PORT_FreeArena(arena,PR_TRUE);
return moduleSpec;
db_loser:
PORT_SetError(SEC_ERROR_BAD_DATABASE);
loser:
PORT_FreeArena(arena,PR_TRUE);
return NULL;
}
static DB *
secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
PRBool readOnly, PRBool update)
{
DB *pkcs11db = NULL;
if (appName) {
char *secname = PORT_Strdup(filename);
int len = strlen(secname);
int status = RDB_FAIL;
if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
secname[len-3] = 0;
}
pkcs11db=
rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
if (update && !pkcs11db) {
DB *updatedb;
pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
if (!pkcs11db) {
if (status == RDB_RETRY) {
pkcs11db= rdbopen(appName, "", secname,
readOnly ? NO_RDONLY:NO_RDWR, NULL);
}
PORT_Free(secname);
return pkcs11db;
}
updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
if (updatedb) {
db_Copy(pkcs11db,updatedb);
(*updatedb->close)(updatedb);
} else {
(*pkcs11db->close)(pkcs11db);
PORT_Free(secname);
return NULL;
}
}
PORT_Free(secname);
return pkcs11db;
}
/* I'm sure we should do more checks here sometime... */
pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
/* didn't exist? create it */
if (pkcs11db == NULL) {
if (readOnly)
return NULL;
pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
if (pkcs11db)
(* pkcs11db->sync)(pkcs11db, 0);
}
return pkcs11db;
}
static void
secmod_CloseDB(DB *pkcs11db)
{
(*pkcs11db->close)(pkcs11db);
}
static char *
secmod_addEscape(const char *string, char quote)
{
char *newString = 0;
int escapes = 0, size = 0;
const char *src;
char *dest;
for (src=string; *src ; src++) {
if ((*src == quote) || (*src == '\\')) escapes++;
size++;
}
newString = PORT_ZAlloc(escapes+size+1);
if (newString == NULL) {
return NULL;
}
for (src=string, dest=newString; *src; src++,dest++) {
if ((*src == '\\') || (*src == quote)) {
*dest++ = '\\';
}
*dest = *src;
}
return newString;
}
SECStatus legacy_AddSecmodDB(const char *appName, const char *filename,
const char *dbname, char *module, PRBool rw);
#define SECMOD_STEP 10
#define SFTK_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\""
/*
* Read all the existing modules in
*/
char **
legacy_ReadSecmodDB(const char *appName, const char *filename,
const char *dbname, char *params, PRBool rw)
{
DBT key,data;
int ret;
DB *pkcs11db = NULL;
char **moduleList = NULL, **newModuleList = NULL;
int moduleCount = 1;
int useCount = SECMOD_STEP;
moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
if (moduleList == NULL) return NULL;
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw);
if (pkcs11db == NULL) goto done;
/* read and parse the file or data base */
ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
if (ret) goto done;
do {
char *moduleString;
PRBool internal = PR_FALSE;
if ((moduleCount+1) >= useCount) {
useCount += SECMOD_STEP;
newModuleList =
(char **)PORT_Realloc(moduleList,useCount*sizeof(char *));
if (newModuleList == NULL) goto done;
moduleList = newModuleList;
PORT_Memset(&moduleList[moduleCount+1],0,
sizeof(char *)*SECMOD_STEP);
}
moduleString = secmod_DecodeData(params,&data,&internal);
if (internal) {
moduleList[0] = moduleString;
} else {
moduleList[moduleCount] = moduleString;
moduleCount++;
}
} while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
done:
if (!moduleList[0]) {
char * newparams = secmod_addEscape(params,'"');
if (newparams) {
moduleList[0] = PR_smprintf(SFTK_DEFAULT_INTERNAL_INIT,newparams,
SECMOD_SLOT_FLAGS);
PORT_Free(newparams);
}
}
/* deal with trust cert db here */
if (pkcs11db) {
secmod_CloseDB(pkcs11db);
} else if (moduleList[0] && rw) {
legacy_AddSecmodDB(appName,filename,dbname,moduleList[0], rw) ;
}
if (!moduleList[0]) {
PORT_Free(moduleList);
moduleList = NULL;
}
return moduleList;
}
SECStatus
legacy_ReleaseSecmodDBData(const char *appName, const char *filename,
const char *dbname, char **moduleSpecList, PRBool rw)
{
if (moduleSpecList) {
char **index;
for(index = moduleSpecList; *index; index++) {
PR_smprintf_free(*index);
}
PORT_Free(moduleSpecList);
}
return SECSuccess;
}
/*
* Delete a module from the Data Base
*/
SECStatus
legacy_DeleteSecmodDB(const char *appName, const char *filename,
const char *dbname, char *args, PRBool rw)
{
DBT key;
SECStatus rv = SECFailure;
DB *pkcs11db = NULL;
int ret;
if (!rw) return SECFailure;
/* make sure we have a db handle */
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
if (pkcs11db == NULL) {
return SECFailure;
}
rv = secmod_MakeKey(&key,args);
if (rv != SECSuccess) goto done;
rv = SECFailure;
ret = (*pkcs11db->del)(pkcs11db, &key, 0);
secmod_FreeKey(&key);
if (ret != 0) goto done;
ret = (*pkcs11db->sync)(pkcs11db, 0);
if (ret == 0) rv = SECSuccess;
done:
secmod_CloseDB(pkcs11db);
return rv;
}
/*
* Add a module to the Data base
*/
SECStatus
legacy_AddSecmodDB(const char *appName, const char *filename,
const char *dbname, char *module, PRBool rw)
{
DBT key,data;
SECStatus rv = SECFailure;
DB *pkcs11db = NULL;
int ret;
if (!rw) return SECFailure;
/* make sure we have a db handle */
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
if (pkcs11db == NULL) {
return SECFailure;
}
rv = secmod_MakeKey(&key,module);
if (rv != SECSuccess) goto done;
rv = secmod_EncodeData(&data,module);
if (rv != SECSuccess) {
secmod_FreeKey(&key);
goto done;
}
rv = SECFailure;
ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
secmod_FreeKey(&key);
secmod_FreeData(&data);
if (ret != 0) goto done;
ret = (*pkcs11db->sync)(pkcs11db, 0);
if (ret == 0) rv = SECSuccess;
done:
secmod_CloseDB(pkcs11db);
return rv;
}

Some files were not shown because too many files have changed in this diff Show More