1999-06-11 01:37:24 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* 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/
|
1999-06-11 01:37:24 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* 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.
|
1999-06-11 01:37:24 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1999-06-11 01:37:24 +00:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 03:40:37 +00:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1999-06-11 01:37:24 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nsFileChannel.h"
|
|
|
|
#include "nscore.h"
|
1999-06-12 01:41:12 +00:00
|
|
|
#include "nsIEventSinkGetter.h"
|
|
|
|
#include "nsIURI.h"
|
|
|
|
#include "nsIEventQueue.h"
|
|
|
|
#include "nsIStreamListener.h"
|
|
|
|
#include "nsIIOService.h"
|
|
|
|
#include "nsIServiceManager.h"
|
1999-06-12 07:14:19 +00:00
|
|
|
#include "nsFileProtocolHandler.h"
|
|
|
|
#include "nsIBufferInputStream.h"
|
|
|
|
#include "nsIBufferOutputStream.h"
|
|
|
|
#include "nsAutoLock.h"
|
|
|
|
#include "netCore.h"
|
1999-08-24 22:30:59 +00:00
|
|
|
#include "nsFileStream.h"
|
1999-06-12 07:14:19 +00:00
|
|
|
#include "nsIFileStream.h"
|
|
|
|
#include "nsISimpleEnumerator.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "prio.h"
|
1999-06-29 23:28:15 +00:00
|
|
|
#include "prmem.h" // XXX can be removed when we start doing real content-type discovery
|
1999-07-16 23:29:12 +00:00
|
|
|
#include "nsCOMPtr.h"
|
1999-07-23 06:16:37 +00:00
|
|
|
#include "nsXPIDLString.h"
|
1999-07-25 18:39:41 +00:00
|
|
|
#include "nsSpecialSystemDirectory.h"
|
1999-07-30 00:55:35 +00:00
|
|
|
#include "nsEscape.h"
|
1999-07-03 00:59:51 +00:00
|
|
|
#include "nsIMIMEService.h"
|
1999-09-16 01:16:22 +00:00
|
|
|
#include "nsIEventQueueService.h"
|
|
|
|
#include "nsIEventQueue.h"
|
|
|
|
#include "nsIFileTransportService.h"
|
1999-07-03 00:59:51 +00:00
|
|
|
|
|
|
|
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
|
1999-06-29 01:52:30 +00:00
|
|
|
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
|
1999-09-16 01:16:22 +00:00
|
|
|
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
|
1999-06-11 01:37:24 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
nsFileChannel::nsFileChannel()
|
1999-09-16 01:16:22 +00:00
|
|
|
: mLoadAttributes(LOAD_NORMAL),
|
1999-09-07 02:54:19 +00:00
|
|
|
mRealListener(nsnull)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
1999-09-16 01:16:22 +00:00
|
|
|
nsFileChannel::Init(nsIFileProtocolHandler* handler, const char* command, nsIURI* uri,
|
1999-10-26 09:16:24 +00:00
|
|
|
nsILoadGroup *aGroup, nsIEventSinkGetter* getter, nsIURI* originalURI)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
mGetter = getter;
|
1999-09-16 01:16:22 +00:00
|
|
|
mHandler = handler;
|
1999-10-26 09:16:24 +00:00
|
|
|
mOriginalURI = originalURI ? originalURI : uri;
|
1999-06-12 01:41:12 +00:00
|
|
|
mURI = uri;
|
1999-09-16 01:16:22 +00:00
|
|
|
mCommand = nsCRT::strdup(command);
|
|
|
|
if (mCommand == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-06-12 01:41:12 +00:00
|
|
|
|
1999-08-26 22:45:55 +00:00
|
|
|
mLoadGroup = aGroup;
|
|
|
|
if (mLoadGroup) {
|
1999-09-16 01:16:22 +00:00
|
|
|
rv = mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-08-26 22:45:55 +00:00
|
|
|
}
|
|
|
|
|
1999-07-23 06:16:37 +00:00
|
|
|
// if we support the nsIURL interface then use it to get just
|
1999-09-06 19:57:40 +00:00
|
|
|
// the file path with no other garbage!
|
|
|
|
nsCOMPtr<nsIURL> aUrl = do_QueryInterface(mURI, &rv);
|
1999-09-16 01:16:22 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && aUrl) { // does it support the url interface?
|
1999-09-06 19:57:40 +00:00
|
|
|
nsXPIDLCString fileString;
|
1999-10-12 01:39:37 +00:00
|
|
|
aUrl->GetFilePath(getter_Copies(fileString));
|
1999-09-06 19:57:40 +00:00
|
|
|
// to be mac friendly you need to convert a file path to a nsFilePath before
|
|
|
|
// passing it to a nsFileSpec...
|
1999-07-25 18:39:41 +00:00
|
|
|
#ifdef XP_MAC
|
1999-09-06 19:57:40 +00:00
|
|
|
nsFilePath filePath(nsUnescape((char*)(const char*)fileString));
|
|
|
|
mSpec = filePath;
|
|
|
|
|
|
|
|
// Don't assume we actually created a good file spec
|
|
|
|
FSSpec theSpec = mSpec.GetFSSpec();
|
|
|
|
if (!theSpec.name[0])
|
|
|
|
{
|
|
|
|
NS_ERROR("failed to create a file spec");
|
|
|
|
|
|
|
|
// Since we didn't actually create the file spec
|
|
|
|
// we return an error
|
|
|
|
return NS_ERROR_MALFORMED_URI;
|
|
|
|
}
|
1999-07-25 18:39:41 +00:00
|
|
|
#else
|
1999-09-06 19:57:40 +00:00
|
|
|
nsFilePath filePath(nsUnescape((char*)(const char*)fileString));
|
|
|
|
mSpec = filePath;
|
1999-07-25 18:39:41 +00:00
|
|
|
#endif
|
1999-09-06 19:57:40 +00:00
|
|
|
}
|
1999-09-16 01:16:22 +00:00
|
|
|
else {
|
1999-09-06 19:57:40 +00:00
|
|
|
// otherwise do the best we can by using the spec for the uri....
|
|
|
|
// XXX temporary, until we integrate more thoroughly with nsFileSpec
|
|
|
|
char* url;
|
|
|
|
rv = mURI->GetSpec(&url);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsFileURL fileURL(url);
|
|
|
|
nsCRT::free(url);
|
|
|
|
mSpec = fileURL;
|
|
|
|
}
|
1999-06-12 01:41:12 +00:00
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
return rv;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsFileChannel::~nsFileChannel()
|
|
|
|
{
|
1999-09-20 20:53:13 +00:00
|
|
|
if (mCommand) nsCRT::free(mCommand);
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aInstancePtr, "no instance pointer");
|
1999-09-03 23:51:14 +00:00
|
|
|
if (aIID.Equals(NS_GET_IID(nsIFileChannel)) ||
|
|
|
|
aIID.Equals(NS_GET_IID(nsIChannel)) ||
|
1999-09-16 01:16:22 +00:00
|
|
|
aIID.Equals(NS_GET_IID(nsIRequest)) ||
|
1999-09-03 23:51:14 +00:00
|
|
|
aIID.Equals(NS_GET_IID(nsISupports))) {
|
1999-06-11 01:37:24 +00:00
|
|
|
*aInstancePtr = NS_STATIC_CAST(nsIFileChannel*, this);
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-09-16 01:16:22 +00:00
|
|
|
if (aIID.Equals(NS_GET_IID(nsIStreamListener)) ||
|
|
|
|
aIID.Equals(NS_GET_IID(nsIStreamObserver))) {
|
|
|
|
*aInstancePtr = NS_STATIC_CAST(nsIStreamListener*, this);
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-09-06 19:57:40 +00:00
|
|
|
return NS_NOINTERFACE;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(nsFileChannel);
|
|
|
|
NS_IMPL_RELEASE(nsFileChannel);
|
|
|
|
|
|
|
|
NS_METHOD
|
|
|
|
nsFileChannel::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
|
|
|
|
{
|
|
|
|
nsFileChannel* fc = new nsFileChannel();
|
|
|
|
if (fc == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(fc);
|
|
|
|
nsresult rv = fc->QueryInterface(aIID, aResult);
|
|
|
|
NS_RELEASE(fc);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-06-12 02:53:21 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// From nsIRequest
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-07-01 19:30:20 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::IsPending(PRBool *result)
|
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
|
|
|
return mFileTransport->IsPending(result);
|
|
|
|
*result = PR_FALSE;
|
1999-09-06 19:57:40 +00:00
|
|
|
return NS_OK;
|
1999-07-01 19:30:20 +00:00
|
|
|
}
|
|
|
|
|
1999-06-12 02:53:21 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::Cancel()
|
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
|
|
|
return mFileTransport->Cancel();
|
|
|
|
return NS_OK;
|
1999-06-12 02:53:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::Suspend()
|
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
|
|
|
return mFileTransport->Suspend();
|
|
|
|
return NS_OK;
|
1999-06-12 02:53:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::Resume()
|
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
|
|
|
return mFileTransport->Resume();
|
|
|
|
return NS_OK;
|
1999-06-12 02:53:21 +00:00
|
|
|
}
|
|
|
|
|
1999-06-11 01:37:24 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// From nsIChannel
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-10-26 09:16:24 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetOriginalURI(nsIURI * *aURI)
|
|
|
|
{
|
|
|
|
*aURI = mOriginalURI;
|
|
|
|
NS_ADDREF(*aURI);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-06-11 01:37:24 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetURI(nsIURI * *aURI)
|
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
*aURI = mURI;
|
1999-09-16 01:16:22 +00:00
|
|
|
NS_ADDREF(*aURI);
|
1999-06-12 01:41:12 +00:00
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-06-12 07:14:19 +00:00
|
|
|
nsFileChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
|
|
|
|
nsIInputStream **result)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-06-12 07:14:19 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
1999-06-12 07:14:19 +00:00
|
|
|
return NS_ERROR_IN_PROGRESS;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
1999-08-03 22:00:17 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
rv = fts->CreateTransport(mSpec, mCommand, mGetter,
|
|
|
|
getter_AddRefs(mFileTransport));
|
1999-06-15 05:18:40 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
return mFileTransport->OpenInputStream(startPosition, readCount, result);
|
1999-06-15 05:18:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
1999-06-15 05:18:40 +00:00
|
|
|
return NS_ERROR_IN_PROGRESS;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
1999-06-15 05:18:40 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-09-16 01:16:22 +00:00
|
|
|
|
|
|
|
rv = fts->CreateTransport(mSpec, mCommand, mGetter,
|
|
|
|
getter_AddRefs(mFileTransport));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return mFileTransport->OpenOutputStream(startPosition, result);
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
1999-10-06 08:26:01 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
1999-06-11 01:37:24 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
|
|
|
|
nsISupports *ctxt,
|
1999-07-20 08:46:33 +00:00
|
|
|
nsIStreamListener *listener)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
nsresult rv;
|
1999-06-12 08:07:05 +00:00
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
|
|
|
return NS_ERROR_IN_PROGRESS;
|
1999-06-29 01:52:30 +00:00
|
|
|
|
1999-09-03 22:03:12 +00:00
|
|
|
mRealListener = listener;
|
1999-10-05 20:54:03 +00:00
|
|
|
nsCOMPtr<nsIStreamListener> tempListener = this;
|
1999-06-12 07:14:19 +00:00
|
|
|
|
1999-08-26 22:45:55 +00:00
|
|
|
if (mLoadGroup) {
|
|
|
|
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
|
|
|
//
|
|
|
|
// Create a load group "proxy" listener...
|
|
|
|
//
|
|
|
|
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
|
|
|
if (factory) {
|
1999-09-16 01:16:22 +00:00
|
|
|
nsIStreamListener *newListener;
|
|
|
|
rv = factory->CreateLoadGroupListener(mRealListener, &newListener);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
mRealListener = newListener;
|
|
|
|
NS_RELEASE(newListener);
|
|
|
|
}
|
1999-08-26 22:45:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rv = mLoadGroup->AddChannel(this, nsnull);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
1999-06-12 07:14:19 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
rv = fts->CreateTransport(mSpec, mCommand, mGetter,
|
|
|
|
getter_AddRefs(mFileTransport));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return mFileTransport->AsyncRead(startPosition, readCount, ctxt, tempListener);
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::AsyncWrite(nsIInputStream *fromStream,
|
|
|
|
PRUint32 startPosition, PRInt32 writeCount,
|
|
|
|
nsISupports *ctxt,
|
1999-07-20 08:46:33 +00:00
|
|
|
nsIStreamObserver *observer)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
nsresult rv;
|
1999-06-12 07:14:19 +00:00
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mFileTransport)
|
|
|
|
return NS_ERROR_IN_PROGRESS;
|
|
|
|
|
|
|
|
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = fts->CreateTransport(mSpec, mCommand, mGetter,
|
|
|
|
getter_AddRefs(mFileTransport));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return mFileTransport->AsyncWrite(fromStream, startPosition, writeCount, ctxt, observer);
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
1999-06-22 00:19:58 +00:00
|
|
|
NS_IMETHODIMP
|
1999-06-24 22:58:42 +00:00
|
|
|
nsFileChannel::GetLoadAttributes(PRUint32 *aLoadAttributes)
|
1999-06-22 00:19:58 +00:00
|
|
|
{
|
1999-06-24 22:58:42 +00:00
|
|
|
*aLoadAttributes = mLoadAttributes;
|
1999-06-22 00:19:58 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-06-24 22:58:42 +00:00
|
|
|
nsFileChannel::SetLoadAttributes(PRUint32 aLoadAttributes)
|
1999-06-22 00:19:58 +00:00
|
|
|
{
|
1999-06-24 22:58:42 +00:00
|
|
|
mLoadAttributes = aLoadAttributes;
|
1999-06-22 00:19:58 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-06-29 23:28:15 +00:00
|
|
|
#define DUMMY_TYPE "text/html"
|
|
|
|
|
1999-06-22 00:19:58 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetContentType(char * *aContentType)
|
|
|
|
{
|
1999-07-23 06:16:37 +00:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
1999-08-24 04:23:55 +00:00
|
|
|
if (mSpec.IsDirectory()) {
|
|
|
|
*aContentType = nsCRT::strdup("application/http-index-format");
|
|
|
|
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-07-03 00:59:51 +00:00
|
|
|
|
1999-08-24 04:23:55 +00:00
|
|
|
rv = MIMEService->GetTypeFromURI(mURI, aContentType);
|
|
|
|
if (NS_SUCCEEDED(rv)) return rv;
|
|
|
|
}
|
1999-07-03 00:59:51 +00:00
|
|
|
|
|
|
|
// if all else fails treat it as text/html?
|
|
|
|
*aContentType = nsCRT::strdup(DUMMY_TYPE);
|
|
|
|
if (!*aContentType) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
} else {
|
1999-07-03 03:54:28 +00:00
|
|
|
return NS_OK;
|
1999-07-03 00:59:51 +00:00
|
|
|
}
|
1999-06-22 00:19:58 +00:00
|
|
|
}
|
|
|
|
|
1999-09-09 05:07:30 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetContentLength(PRInt32 *aContentLength)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
PRUint32 length;
|
|
|
|
|
|
|
|
rv = GetFileSize(&length);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
*aContentLength = (PRInt32)length;
|
|
|
|
} else {
|
|
|
|
*aContentLength = -1;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-07-31 06:53:12 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
|
|
|
|
{
|
|
|
|
*aLoadGroup = mLoadGroup;
|
|
|
|
NS_IF_ADDREF(*aLoadGroup);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-08-29 21:58:42 +00:00
|
|
|
NS_IMETHODIMP
|
1999-09-11 18:45:36 +00:00
|
|
|
nsFileChannel::GetOwner(nsISupports * *aOwner)
|
1999-08-29 21:58:42 +00:00
|
|
|
{
|
1999-09-11 19:43:06 +00:00
|
|
|
*aOwner = mOwner.get();
|
1999-09-11 18:45:36 +00:00
|
|
|
NS_IF_ADDREF(*aOwner);
|
1999-08-29 21:58:42 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-09-11 18:45:36 +00:00
|
|
|
nsFileChannel::SetOwner(nsISupports * aOwner)
|
1999-08-29 21:58:42 +00:00
|
|
|
{
|
1999-09-11 18:45:36 +00:00
|
|
|
mOwner = aOwner;
|
1999-08-29 21:58:42 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-07-31 06:53:12 +00:00
|
|
|
|
1999-08-26 22:45:55 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsIStreamListener methods:
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-09-16 01:16:22 +00:00
|
|
|
nsFileChannel::OnStartRequest(nsIChannel* transportChannel, nsISupports* context)
|
1999-08-26 22:45:55 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION(mRealListener, "No listener...");
|
1999-09-16 01:16:22 +00:00
|
|
|
return mRealListener->OnStartRequest(this, context);
|
1999-08-26 22:45:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-09-16 01:16:22 +00:00
|
|
|
nsFileChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
|
|
|
|
nsresult aStatus, const PRUnichar* aMsg)
|
1999-08-26 22:45:55 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
rv = mRealListener->OnStopRequest(this, context, aStatus, aMsg);
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-08-26 22:45:55 +00:00
|
|
|
if (mLoadGroup) {
|
1999-09-16 01:16:22 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
mLoadGroup->RemoveChannel(this, context, aStatus, aMsg);
|
|
|
|
}
|
1999-08-26 22:45:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Release the reference to the consumer stream listener...
|
|
|
|
mRealListener = null_nsCOMPtr();
|
1999-09-16 01:16:22 +00:00
|
|
|
mFileTransport = null_nsCOMPtr();
|
1999-08-26 22:45:55 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
|
|
|
|
nsIInputStream *aIStream, PRUint32 aSourceOffset,
|
|
|
|
PRUint32 aLength)
|
|
|
|
{
|
|
|
|
return mRealListener->OnDataAvailable(this, context, aIStream,
|
|
|
|
aSourceOffset, aLength);
|
|
|
|
}
|
|
|
|
|
1999-06-11 01:37:24 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// From nsIFileChannel
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetModDate(PRTime *aModDate)
|
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
nsFileSpec::TimeStamp date;
|
|
|
|
mSpec.GetModDate(date);
|
1999-06-11 01:37:24 +00:00
|
|
|
LL_I2L(*aModDate, date);
|
1999-06-12 01:41:12 +00:00
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetFileSize(PRUint32 *aFileSize)
|
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
*aFileSize = mSpec.GetFileSize();
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetParent(nsIFileChannel * *aParent)
|
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
nsFileSpec parentSpec;
|
|
|
|
mSpec.GetParent(parentSpec);
|
1999-08-24 22:30:59 +00:00
|
|
|
return CreateFileChannelFromFileSpec(parentSpec, aParent);
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
1999-06-12 07:14:19 +00:00
|
|
|
class nsDirEnumerator : public nsISimpleEnumerator
|
|
|
|
{
|
1999-09-06 19:57:40 +00:00
|
|
|
public:
|
1999-06-12 07:14:19 +00:00
|
|
|
NS_DECL_ISUPPORTS
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
nsDirEnumerator() : mDir(nsnull) {
|
1999-06-12 07:14:19 +00:00
|
|
|
NS_INIT_REFCNT();
|
|
|
|
}
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
nsresult Init(nsIFileProtocolHandler* handler, nsFileSpec& spec) {
|
1999-06-12 07:14:19 +00:00
|
|
|
const char* path = spec.GetNativePathCString();
|
|
|
|
mDir = PR_OpenDir(path);
|
|
|
|
if (mDir == nsnull) // not a directory?
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
mHandler = handler;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD HasMoreElements(PRBool *result) {
|
|
|
|
nsresult rv;
|
|
|
|
if (mNext == nsnull && mDir) {
|
|
|
|
PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
|
|
|
|
if (entry == nsnull) {
|
|
|
|
// end of dir entries
|
|
|
|
|
|
|
|
PRStatus status = PR_CloseDir(mDir);
|
1999-09-06 19:57:40 +00:00
|
|
|
if (status != PR_SUCCESS)
|
1999-06-12 07:14:19 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
mDir = nsnull;
|
|
|
|
|
|
|
|
*result = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* path = entry->name;
|
1999-09-16 01:16:22 +00:00
|
|
|
rv = mHandler->NewChannelFromNativePath(path, getter_AddRefs(mNext));
|
1999-06-12 07:14:19 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
NS_ASSERTION(mNext, "NewChannel failed");
|
1999-09-06 19:57:40 +00:00
|
|
|
}
|
1999-06-12 07:14:19 +00:00
|
|
|
*result = mNext != nsnull;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD GetNext(nsISupports **result) {
|
|
|
|
nsresult rv;
|
|
|
|
PRBool hasMore;
|
|
|
|
rv = HasMoreElements(&hasMore);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
*result = mNext; // might return nsnull
|
1999-09-16 01:16:22 +00:00
|
|
|
mNext = null_nsCOMPtr();
|
1999-06-12 07:14:19 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~nsDirEnumerator() {
|
|
|
|
if (mDir) {
|
|
|
|
PRStatus status = PR_CloseDir(mDir);
|
|
|
|
NS_ASSERTION(status == PR_SUCCESS, "close failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
1999-09-16 01:16:22 +00:00
|
|
|
nsCOMPtr<nsIFileProtocolHandler> mHandler;
|
|
|
|
PRDir* mDir;
|
|
|
|
nsCOMPtr<nsIFileChannel> mNext;
|
1999-06-12 07:14:19 +00:00
|
|
|
};
|
|
|
|
|
1999-09-03 23:51:14 +00:00
|
|
|
NS_IMPL_ISUPPORTS(nsDirEnumerator, NS_GET_IID(nsISimpleEnumerator));
|
1999-06-12 07:14:19 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetChildren(nsISimpleEnumerator * *aChildren)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-09-06 19:57:40 +00:00
|
|
|
PRBool isDir;
|
1999-06-12 07:14:19 +00:00
|
|
|
rv = IsDirectory(&isDir);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!isDir)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsDirEnumerator* dirEnum = new nsDirEnumerator();
|
|
|
|
if (dirEnum == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(dirEnum);
|
|
|
|
rv = dirEnum->Init(mHandler, mSpec);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_RELEASE(dirEnum);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
*aChildren = dirEnum;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-06-11 01:37:24 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::GetNativePath(char * *aNativePath)
|
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
char* nativePath = nsCRT::strdup(mSpec.GetNativePathCString());
|
|
|
|
if (nativePath == nsnull)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
*aNativePath = nativePath;
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-06-12 01:41:12 +00:00
|
|
|
nsFileChannel::Exists(PRBool *result)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
*result = mSpec.Exists();
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::Create()
|
|
|
|
{
|
1999-08-25 00:19:00 +00:00
|
|
|
nsFileSpec mySpec(mSpec); // relative path.
|
1999-08-24 22:30:59 +00:00
|
|
|
{
|
|
|
|
nsIOFileStream testStream(mySpec); // creates the file
|
|
|
|
// Scope ends here, file gets closed
|
|
|
|
}
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::Delete()
|
|
|
|
{
|
1999-08-24 22:30:59 +00:00
|
|
|
mSpec.Delete(PR_TRUE); // RECURSIVE DELETE!
|
|
|
|
if (mSpec.Exists())
|
|
|
|
return NS_ERROR_FAILURE;
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-08-24 22:30:59 +00:00
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::MoveFrom(nsIURI *src)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
nsresult rv;
|
1999-06-12 01:41:12 +00:00
|
|
|
nsIFileChannel* fc;
|
1999-09-03 23:51:14 +00:00
|
|
|
rv = src->QueryInterface(NS_GET_IID(nsIFileChannel), (void**)&fc);
|
1999-06-11 01:37:24 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
1999-06-12 01:41:12 +00:00
|
|
|
rv = fc->moveToDir(this);
|
|
|
|
NS_RELEASE(fc);
|
1999-06-11 01:37:24 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Do it the hard way -- fetch the URL and store the bits locally.
|
|
|
|
// Delete the src when done.
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::CopyFrom(nsIURI *src)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
nsresult rv;
|
1999-06-12 01:41:12 +00:00
|
|
|
nsIFileChannel* fc;
|
1999-09-03 23:51:14 +00:00
|
|
|
rv = src->QueryInterface(NS_GET_IID(nsIFileChannel), (void**)&fc);
|
1999-06-11 01:37:24 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
1999-06-12 01:41:12 +00:00
|
|
|
rv = fc->copyToDir(this);
|
|
|
|
NS_RELEASE(fc);
|
1999-06-11 01:37:24 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Do it the hard way -- fetch the URL and store the bits locally.
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-06-12 01:41:12 +00:00
|
|
|
nsFileChannel::IsDirectory(PRBool *result)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
*result = mSpec.IsDirectory();
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-06-12 01:41:12 +00:00
|
|
|
nsFileChannel::IsFile(PRBool *result)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-06-12 01:41:12 +00:00
|
|
|
*result = mSpec.IsFile();
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::IsLink(PRBool *_retval)
|
|
|
|
{
|
1999-08-24 22:30:59 +00:00
|
|
|
*_retval = mSpec.IsSymlink();
|
|
|
|
return NS_OK;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::ResolveLink(nsIFileChannel **_retval)
|
|
|
|
{
|
1999-08-24 22:30:59 +00:00
|
|
|
PRBool ignore;
|
|
|
|
nsFileSpec tempSpec = mSpec;
|
|
|
|
nsresult rv = tempSpec.ResolveSymlink(ignore);
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
1999-08-24 22:30:59 +00:00
|
|
|
return CreateFileChannelFromFileSpec(tempSpec, _retval);
|
|
|
|
}
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-08-24 22:30:59 +00:00
|
|
|
return rv;
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-08-24 22:30:59 +00:00
|
|
|
nsFileChannel::MakeUnique(const char* baseName, nsIFileChannel **_retval)
|
1999-06-11 01:37:24 +00:00
|
|
|
{
|
1999-09-16 01:16:22 +00:00
|
|
|
if (mSpec.IsDirectory()) {
|
1999-08-24 22:30:59 +00:00
|
|
|
nsFileSpec tempSpec = mSpec;
|
|
|
|
tempSpec.MakeUnique(baseName);
|
|
|
|
|
|
|
|
return CreateFileChannelFromFileSpec(tempSpec, _retval);
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE; // XXX probably need NS_BASE_STREAM_NOT_DIRECTORY or something
|
1999-06-11 01:37:24 +00:00
|
|
|
}
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-06-11 01:37:24 +00:00
|
|
|
|
1999-06-12 07:14:19 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFileChannel::Execute(const char *args)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
char* queryArgs = nsnull;
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-06-12 07:14:19 +00:00
|
|
|
if (args == nsnull) {
|
|
|
|
nsIURL* url;
|
1999-09-03 23:51:14 +00:00
|
|
|
rv = mURI->QueryInterface(NS_GET_IID(nsIURL), (void**)&url);
|
1999-06-12 07:14:19 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = url->GetQuery(&queryArgs);
|
|
|
|
NS_RELEASE(url);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
args = queryArgs;
|
|
|
|
}
|
|
|
|
}
|
1999-09-06 19:57:40 +00:00
|
|
|
|
1999-06-12 07:14:19 +00:00
|
|
|
rv = mSpec.Execute(args);
|
|
|
|
if (queryArgs)
|
|
|
|
nsCRT::free(queryArgs);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
1999-08-27 10:33:37 +00:00
|
|
|
|
1999-08-24 22:30:59 +00:00
|
|
|
nsresult
|
|
|
|
nsFileChannel::CreateFileChannelFromFileSpec(nsFileSpec& spec, nsIFileChannel **result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsFileURL aURL(spec);
|
|
|
|
const char* urlStr = aURL.GetURLString();
|
|
|
|
|
|
|
|
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsIChannel* channel;
|
|
|
|
rv = serv->NewChannel("load", // XXX what should this be?
|
1999-09-06 19:57:40 +00:00
|
|
|
urlStr,
|
1999-08-24 22:30:59 +00:00
|
|
|
nsnull,
|
1999-08-26 22:45:55 +00:00
|
|
|
mLoadGroup,
|
1999-09-06 19:57:40 +00:00
|
|
|
mGetter,
|
1999-10-26 09:16:24 +00:00
|
|
|
nsnull,
|
1999-08-24 22:30:59 +00:00
|
|
|
&channel);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// this cast is safe because nsFileURL::GetURLString aways
|
|
|
|
// returns file: strings, and consequently we'll make nsIFileChannel
|
|
|
|
// objects from them:
|
|
|
|
*result = NS_STATIC_CAST(nsIFileChannel*, channel);
|
|
|
|
return NS_OK;
|
1999-08-25 21:21:22 +00:00
|
|
|
}
|
|
|
|
|
1999-09-16 01:16:22 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|