mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-04-02 20:42:49 +00:00
adding multipartmixed stream converter implementation NOTE: it's not part of the build yet
This commit is contained in:
parent
f4f7d3591c
commit
271b4483c7
55
netwerk/streamconv/converters/makefile.win
Normal file
55
netwerk/streamconv/converters/makefile.win
Normal file
@ -0,0 +1,55 @@
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ..\..\..
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = necko
|
||||
|
||||
IS_COMPONENT=1
|
||||
MAKE_OBJ_TYPE=DLL
|
||||
DLLNAME=cnvts
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
|
||||
EXPORTS = \
|
||||
nsMultiMixedConv.h \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= $(LLIBS) \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
LCFLAGS = -DWIN32_LEAN_AND_MEAN -D_IMPL_NS_NET
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsMultiMixedConv.obj \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES=-I.
|
||||
|
||||
INCLUDES = $(LOCAL_INCLUDES)
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\dist\include \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(DLL)
|
||||
$(MAKE_INSTALL) $(DLL) $(DIST)\bin\components
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
359
netwerk/streamconv/converters/nsMultiMixedConv.cpp
Normal file
359
netwerk/streamconv/converters/nsMultiMixedConv.cpp
Normal file
@ -0,0 +1,359 @@
|
||||
#include "nsMultiMixedConv.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "plstr.h"
|
||||
#include "nsIStringStream.h"
|
||||
#include "nsIHTTPChannel.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsCOMPtr.h"
|
||||
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
|
||||
|
||||
|
||||
|
||||
// nsISupports implementation
|
||||
NS_IMPL_ISUPPORTS2(nsMultiMixedConv, nsIStreamConverter, nsIStreamListener);
|
||||
|
||||
|
||||
// nsIStreamConverter implementation
|
||||
NS_IMETHODIMP
|
||||
nsMultiMixedConv::Convert(nsIInputStream *aFromStream,
|
||||
const PRUnichar *aFromType,
|
||||
const PRUnichar *aToType,
|
||||
nsISupports *aCtxt, nsIInputStream **_retval) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMultiMixedConv::AsyncConvertData(const PRUnichar *aFromType, const PRUnichar *aToType,
|
||||
nsIStreamListener *aListener, nsISupports *aCtxt) {
|
||||
NS_ASSERTION(aListener && aFromType && aToType, "null pointer passed into multi mixed converter");
|
||||
|
||||
mFinalListener = aListener;
|
||||
NS_ADDREF(mFinalListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIStreamListener implementation
|
||||
NS_IMETHODIMP
|
||||
nsMultiMixedConv::OnDataAvailable(nsIChannel *channel, nsISupports *ctxt,
|
||||
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
|
||||
nsresult rv;
|
||||
char *buffer = nsnull, *rootMemPtr = nsnull, *delimiter = nsnull, *bndry = nsnull;
|
||||
PRUint32 bufLen, read;
|
||||
rv = inStr->GetLength(&bufLen);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsIHTTPChannel *HTTPChannel= nsnull;
|
||||
if (!mBoundaryCStr && channel) {
|
||||
rv = channel->QueryInterface(NS_GET_IID(nsIHTTPChannel), (void**)&HTTPChannel);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// XXX shouldn't return failure in this case. what to do?
|
||||
|
||||
nsIAtom *header = NS_NewAtom("content-type");
|
||||
if (!header) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
rv = HTTPChannel->GetResponseHeader(header, &delimiter);
|
||||
NS_RELEASE(header);
|
||||
NS_RELEASE(HTTPChannel);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
bndry = PL_strstr(delimiter, bndry);
|
||||
if (!bndry) {
|
||||
// if we dont' have a boundary we're hosed.
|
||||
;
|
||||
}
|
||||
|
||||
bndry = PL_strchr(bndry, '=');
|
||||
if (!bndry) {
|
||||
// ""
|
||||
;
|
||||
}
|
||||
|
||||
bndry += 1;
|
||||
|
||||
nsString2 boundaryString(bndry, eOneByte);
|
||||
boundaryString.StripWhitespace();
|
||||
mBoundaryCStr = boundaryString.ToNewCString();
|
||||
if (!mBoundaryCStr) return NS_ERROR_OUT_OF_MEMORY;
|
||||
mBoundaryStrLen = boundaryString.Length();
|
||||
|
||||
}
|
||||
#if 1
|
||||
nsString2 test("--aBoundary", eOneByte);
|
||||
mBoundaryCStr = test.ToNewCString();
|
||||
mBoundaryStrLen = test.Length();
|
||||
#endif
|
||||
|
||||
buffer = (char*)nsAllocator::Alloc(bufLen);
|
||||
if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = inStr->Read(buffer, bufLen, &read);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
buffer[bufLen] = '\0';
|
||||
|
||||
if (!mBuffer.IsEmpty()) {
|
||||
// don't forget about any data that was left in the buffer.
|
||||
mBuffer.Append(buffer);
|
||||
//nsAllocator::Free(buffer);
|
||||
rootMemPtr = buffer = mBuffer.ToNewCString();
|
||||
}
|
||||
|
||||
// search the buffered data for the delimiting token.
|
||||
char *boundaryLoc = PL_strstr(buffer, mBoundaryCStr);
|
||||
do {
|
||||
if (boundaryLoc) {
|
||||
// check for another
|
||||
char *boundaryLoc2 = PL_strstr(boundaryLoc + mBoundaryStrLen, mBoundaryCStr);
|
||||
|
||||
if (!mBoundaryStart) {
|
||||
mBoundaryStart = PR_TRUE;
|
||||
// XXX we need to set the http headers that can sit within each boundary.
|
||||
|
||||
if (boundaryLoc2) {
|
||||
// there was another boundary loc (signifying the end of this part)
|
||||
// in the buffer. Build up this hunk and fire it off.
|
||||
char tmpChar = *boundaryLoc2;
|
||||
*boundaryLoc2 = '\0';
|
||||
|
||||
rv = SendPart(boundaryLoc + mBoundaryStrLen, channel, ctxt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*boundaryLoc2 = tmpChar;
|
||||
|
||||
// increment the buffer and start over.
|
||||
buffer = boundaryLoc2;
|
||||
mBoundaryStart = PR_FALSE;
|
||||
boundaryLoc = PL_strstr(buffer, mBoundaryCStr);
|
||||
} else {
|
||||
buffer = boundaryLoc + mBoundaryStrLen;
|
||||
mBuffer.Append(buffer);
|
||||
boundaryLoc = PL_strstr(buffer, mBoundaryCStr);
|
||||
}
|
||||
} else {
|
||||
// this boundaryLoc is an ending delimiter. package up the data and send it off
|
||||
mBoundaryStart = PR_FALSE;
|
||||
char tmpChar = *boundaryLoc;
|
||||
*boundaryLoc = '\0';
|
||||
|
||||
rv = SendPart(buffer, channel, ctxt);
|
||||
|
||||
*boundaryLoc = tmpChar;
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
buffer = boundaryLoc;
|
||||
mBuffer = buffer;
|
||||
boundaryLoc = PL_strstr(buffer, mBoundaryCStr);
|
||||
}
|
||||
} else {
|
||||
mBuffer.Append(buffer);
|
||||
}
|
||||
} while (boundaryLoc);
|
||||
|
||||
//nsAllocator::Free((char*)rootMemPtr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIStreamObserver implementation
|
||||
NS_IMETHODIMP
|
||||
nsMultiMixedConv::OnStartRequest(nsIChannel *channel, nsISupports *ctxt) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMultiMixedConv::OnStopRequest(nsIChannel *channel, nsISupports *ctxt,
|
||||
nsresult status, const PRUnichar *errorMsg) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsMultiMixedConv methods
|
||||
nsMultiMixedConv::nsMultiMixedConv() {
|
||||
NS_INIT_ISUPPORTS();
|
||||
mFinalListener = nsnull;
|
||||
mBoundaryCStr = nsnull;
|
||||
mBoundaryStrLen = 0;
|
||||
}
|
||||
|
||||
nsMultiMixedConv::~nsMultiMixedConv() {
|
||||
NS_IF_RELEASE(mFinalListener);
|
||||
if (mBoundaryCStr) nsAllocator::Free(mBoundaryCStr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMultiMixedConv::Init() {
|
||||
mBoundaryStart = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMultiMixedConv::SendPart(const char *aBuffer, nsIChannel *aChannel, nsISupports *aCtxt) {
|
||||
|
||||
nsresult rv;
|
||||
// fire off the "part"
|
||||
rv = mFinalListener->OnStartRequest(aChannel, aCtxt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
nsISupports *stringStreamSup = nsnull;
|
||||
rv = NS_NewStringInputStream(&stringStreamSup, aBuffer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsIInputStream *inStr = nsnull;
|
||||
rv = stringStreamSup->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inStr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 len;
|
||||
rv = inStr->GetLength(&len);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mFinalListener->OnDataAvailable(aChannel, aCtxt, inStr, 0, len);
|
||||
NS_RELEASE(stringStreamSup);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mFinalListener->OnStopRequest(aChannel, aCtxt, NS_OK, nsnull);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Factory
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
MultiMixedFactory::MultiMixedFactory(const nsCID &aClass,
|
||||
const char* className,
|
||||
const char* progID)
|
||||
: mClassID(aClass), mClassName(className), mProgID(progID)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
MultiMixedFactory::~MultiMixedFactory()
|
||||
{
|
||||
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(MultiMixedFactory, NS_GET_IID(nsIFactory));
|
||||
|
||||
NS_IMETHODIMP
|
||||
MultiMixedFactory::CreateInstance(nsISupports *aOuter,
|
||||
const nsIID &aIID,
|
||||
void **aResult)
|
||||
{
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
*aResult = nsnull;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsISupports *inst = nsnull;
|
||||
if (mClassID.Equals(kMultiMixedConverterCID)) {
|
||||
nsMultiMixedConv *conv = new nsMultiMixedConv();
|
||||
if (!conv) return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = conv->Init();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = conv->QueryInterface(NS_GET_IID(nsISupports), (void**)&inst);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
if (!inst)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(inst);
|
||||
*aResult = inst;
|
||||
NS_RELEASE(inst);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MultiMixedFactory::LockFactory(PRBool aLock)
|
||||
{
|
||||
// Not implemented in simplest case.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// return the proper factory to the caller
|
||||
extern "C" PR_IMPLEMENT(nsresult)
|
||||
NSGetFactory(nsISupports* aServMgr,
|
||||
const nsCID &aClass,
|
||||
const char *aClassName,
|
||||
const char *aProgID,
|
||||
nsIFactory **aFactory)
|
||||
{
|
||||
nsresult rv;
|
||||
if (aFactory == nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIGenericFactory* fact;
|
||||
if (aClass.Equals(kMultiMixedConverterCID)) {
|
||||
rv = NS_NewGenericFactory(&fact, nsMultiMixedConv::Create);
|
||||
}
|
||||
else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
*aFactory = fact;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" PR_IMPLEMENT(nsresult)
|
||||
NSRegisterSelf(nsISupports* aServMgr , const char* aPath)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIServiceManager> servMgr(do_QueryInterface(aServMgr, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIComponentManager, compMgr, kComponentManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = compMgr->RegisterComponent(kMultiMixedConverterCID,
|
||||
"MultiMixedConverter",
|
||||
"component:||netscape|streamConverters|multimixedconverter",
|
||||
aPath, PR_TRUE, PR_TRUE);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
extern "C" PR_IMPLEMENT(nsresult)
|
||||
NSUnregisterSelf(nsISupports* aServMgr, const char* aPath)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIServiceManager> servMgr(do_QueryInterface(aServMgr, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIComponentManager, compMgr, kComponentManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = compMgr->UnregisterComponent(kMultiMixedConverterCID, aPath);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Factory END
|
||||
////////////////////////////////////////////////////////////////////////
|
98
netwerk/streamconv/converters/nsMultiMixedConv.h
Normal file
98
netwerk/streamconv/converters/nsMultiMixedConv.h
Normal file
@ -0,0 +1,98 @@
|
||||
#include "nsIStreamConverter.h"
|
||||
#include "nsString2.h"
|
||||
|
||||
#include "nsIFactory.h"
|
||||
|
||||
#define NS_MULTIMIXEDCONVERTER_CID \
|
||||
{ /* 7584CE90-5B25-11d3-A175-0050041CAF44 */ \
|
||||
0x7584ce90, \
|
||||
0x5b25, \
|
||||
0x11d3, \
|
||||
{0xa1, 0x75, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44} \
|
||||
}
|
||||
static NS_DEFINE_CID(kMultiMixedConverterCID, NS_MULTIMIXEDCONVERTER_CID);
|
||||
|
||||
|
||||
class nsMultiMixedConv : public nsIStreamConverter {
|
||||
public:
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIStreamConverter methods
|
||||
NS_IMETHOD Convert(nsIInputStream *aFromStream,
|
||||
const PRUnichar *aFromType,
|
||||
const PRUnichar *aToType,
|
||||
nsISupports *aCtxt, nsIInputStream **_retval);
|
||||
|
||||
NS_IMETHOD AsyncConvertData(const PRUnichar *aFromType, const PRUnichar *aToType,
|
||||
nsIStreamListener *aListener, nsISupports *aCtxt);
|
||||
|
||||
// nsIStreamListener methods
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel *channel, nsISupports *ctxt,
|
||||
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count);
|
||||
|
||||
// nsIStreamObserver methods
|
||||
NS_IMETHOD OnStartRequest(nsIChannel *channel, nsISupports *ctxt);
|
||||
NS_IMETHOD OnStopRequest(nsIChannel *channel, nsISupports *ctxt,
|
||||
nsresult status, const PRUnichar *errorMsg);
|
||||
|
||||
// nsMultiMixedConv methods
|
||||
nsMultiMixedConv();
|
||||
~nsMultiMixedConv();
|
||||
nsresult Init();
|
||||
nsresult SendPart(const char *aBuffer, nsIChannel *aChannel, nsISupports *aCtxt);
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
|
||||
nsresult rv;
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsMultiMixedConv* _s = new nsMultiMixedConv();
|
||||
if (_s == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(_s);
|
||||
rv = _s->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
delete _s;
|
||||
return rv;
|
||||
}
|
||||
rv = _s->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(_s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// member data
|
||||
nsCAutoString mBuffer;
|
||||
PRBool mBoundaryStart;
|
||||
nsCAutoString *mBoundryString;
|
||||
nsIStreamListener *mFinalListener;
|
||||
char *mBoundaryCStr;
|
||||
PRInt32 mBoundaryStrLen;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// FACTORY
|
||||
class MultiMixedFactory : public nsIFactory
|
||||
{
|
||||
public:
|
||||
MultiMixedFactory(const nsCID &aClass, const char* className, const char* progID);
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFactory methods
|
||||
NS_IMETHOD CreateInstance(nsISupports *aOuter,
|
||||
const nsIID &aIID,
|
||||
void **aResult);
|
||||
|
||||
NS_IMETHOD LockFactory(PRBool aLock);
|
||||
|
||||
protected:
|
||||
virtual ~MultiMixedFactory();
|
||||
|
||||
protected:
|
||||
nsCID mClassID;
|
||||
const char* mClassName;
|
||||
const char* mProgID;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user