1999-06-05 01:41:47 +04:00
|
|
|
/* -*- 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.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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "msgCore.h"
|
|
|
|
#include "nsMsgProtocol.h"
|
1999-06-06 00:21:27 +04:00
|
|
|
#include "nsIMsgMailNewsUrl.h"
|
1999-07-29 04:42:25 +04:00
|
|
|
#include "nsISocketTransportService.h"
|
|
|
|
#include "nsXPIDLString.h"
|
1999-09-01 08:09:07 +04:00
|
|
|
#include "nsSpecialSystemDirectory.h"
|
1999-07-29 04:42:25 +04:00
|
|
|
#include "nsIIOService.h"
|
1999-06-05 01:41:47 +04:00
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
1999-06-05 01:41:47 +04:00
|
|
|
|
1999-07-01 04:16:39 +04:00
|
|
|
NS_IMPL_ISUPPORTS(nsMsgProtocol, nsCOMTypeInfo<nsIStreamListener>::GetIID())
|
1999-06-05 01:41:47 +04:00
|
|
|
|
|
|
|
nsMsgProtocol::nsMsgProtocol()
|
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
m_flags = 0;
|
1999-07-29 04:42:25 +04:00
|
|
|
m_startPosition = 0;
|
|
|
|
m_readCount = 0;
|
1999-06-05 01:41:47 +04:00
|
|
|
m_socketIsOpen = PR_FALSE;
|
1999-09-01 08:09:07 +04:00
|
|
|
|
|
|
|
m_tempMsgFileSpec = nsSpecialSystemDirectory(nsSpecialSystemDirectory::OS_TemporaryDirectory);
|
|
|
|
m_tempMsgFileSpec += "tempMessage.eml";
|
1999-06-05 01:41:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsMsgProtocol::~nsMsgProtocol()
|
|
|
|
{}
|
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
nsresult nsMsgProtocol::OpenNetworkSocket(nsIURI * aURL) // open a connection on this url
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
1999-07-29 04:42:25 +04:00
|
|
|
nsXPIDLCString hostName;
|
|
|
|
PRInt32 port = 0;
|
1999-06-05 01:41:47 +04:00
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
m_readCount = -1; // with socket connections we want to read as much data as arrives
|
|
|
|
m_startPosition = 0;
|
|
|
|
|
|
|
|
NS_WITH_SERVICE(nsISocketTransportService, socketService, kSocketTransportServiceCID, &rv);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && aURL)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
aURL->GetPort(&port);
|
|
|
|
aURL->GetHost(getter_Copies(hostName));
|
|
|
|
|
|
|
|
rv = socketService->CreateTransport(hostName, port, getter_AddRefs(m_channel));
|
|
|
|
if (NS_SUCCEEDED(rv) && m_channel)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
m_socketIsOpen = PR_FALSE;
|
1999-06-05 01:41:47 +04:00
|
|
|
rv = SetupTransportState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
nsresult nsMsgProtocol::OpenFileSocket(nsIURI * aURL, const nsFileSpec * aFileSpec, PRUint32 aStartPosition, PRInt32 aReadCount)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
// mscott - file needs to be encoded directly into aURL. I should be able to get
|
|
|
|
// rid of this method completely.
|
|
|
|
|
1999-06-05 01:41:47 +04:00
|
|
|
nsresult rv = NS_OK;
|
1999-07-29 04:42:25 +04:00
|
|
|
m_startPosition = aStartPosition;
|
|
|
|
m_readCount = aReadCount;
|
|
|
|
|
|
|
|
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv) && aURL)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
// extract the file path from the uri...
|
|
|
|
nsXPIDLCString filePath;
|
|
|
|
aURL->GetPath(getter_Copies(filePath));
|
|
|
|
char * urlSpec = PR_smprintf("file://%s", (const char *) filePath);
|
|
|
|
|
1999-08-27 02:45:55 +04:00
|
|
|
rv = netService->NewChannel("Load", urlSpec,
|
|
|
|
nsnull, // null base URI
|
|
|
|
nsnull, // null load group
|
|
|
|
nsnull, // null eventsink getter
|
|
|
|
getter_AddRefs(m_channel));
|
1999-07-29 04:42:25 +04:00
|
|
|
PR_FREEIF(urlSpec);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && m_channel)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
m_socketIsOpen = PR_FALSE;
|
|
|
|
// rv = SetupTransportState();
|
1999-06-05 01:41:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsMsgProtocol::SetupTransportState()
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
if (!m_socketIsOpen && m_channel)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
rv = m_channel->OpenOutputStream(0 /* start position */, getter_AddRefs(m_outputStream));
|
1999-06-05 01:41:47 +04:00
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create an output stream");
|
|
|
|
// we want to open the stream
|
1999-06-05 01:41:47 +04:00
|
|
|
} // if m_transport
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsMsgProtocol::CloseSocket()
|
|
|
|
{
|
|
|
|
// release all of our socket state
|
|
|
|
m_socketIsOpen = PR_FALSE;
|
|
|
|
m_outputStream = null_nsCOMPtr();
|
1999-07-29 04:42:25 +04:00
|
|
|
m_channel = null_nsCOMPtr();
|
1999-06-05 01:41:47 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Writes the data contained in dataBuffer into the current output stream. It also informs
|
|
|
|
* the transport layer that this data is now available for transmission.
|
|
|
|
* Returns a positive number for success, 0 for failure (not all the bytes were written to the
|
|
|
|
* stream, etc). We need to make another pass through this file to install an error system (mscott)
|
|
|
|
*/
|
|
|
|
|
1999-06-23 07:29:44 +04:00
|
|
|
PRInt32 nsMsgProtocol::SendData(nsIURI * aURL, const char * dataBuffer)
|
1999-06-05 01:41:47 +04:00
|
|
|
{
|
|
|
|
PRUint32 writeCount = 0;
|
|
|
|
PRInt32 status = 0;
|
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
// NS_PRECONDITION(m_outputStream, "oops....we don't have an output stream...how did that happen?");
|
1999-06-05 01:41:47 +04:00
|
|
|
if (dataBuffer && m_outputStream)
|
|
|
|
{
|
1999-08-05 00:35:58 +04:00
|
|
|
status = m_outputStream->Write(dataBuffer, PL_strlen(dataBuffer), &writeCount);
|
1999-06-05 01:41:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
1999-06-06 00:21:27 +04:00
|
|
|
|
|
|
|
// Whenever data arrives from the connection, core netlib notifices the protocol by calling
|
|
|
|
// OnDataAvailable. We then read and process the incoming data from the input stream.
|
1999-07-29 04:42:25 +04:00
|
|
|
NS_IMETHODIMP nsMsgProtocol::OnDataAvailable(nsIChannel * /* aChannel */, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
|
1999-06-06 00:21:27 +04:00
|
|
|
{
|
|
|
|
// right now, this really just means turn around and churn through the state machine
|
1999-07-29 04:42:25 +04:00
|
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(ctxt);
|
|
|
|
return ProcessProtocolState(uri, inStr, sourceOffset, count);
|
1999-06-06 00:21:27 +04:00
|
|
|
}
|
|
|
|
|
1999-07-29 04:42:25 +04:00
|
|
|
NS_IMETHODIMP nsMsgProtocol::OnStartRequest(nsIChannel * aChannel, nsISupports *ctxt)
|
1999-06-06 00:21:27 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(ctxt, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
|
|
|
return aMsgUrl->SetUrlState(PR_TRUE, NS_OK);
|
|
|
|
else
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
1999-06-06 00:21:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// stop binding is a "notification" informing us that the stream associated with aURL is going away.
|
1999-07-29 04:42:25 +04:00
|
|
|
NS_IMETHODIMP nsMsgProtocol::OnStopRequest(nsIChannel * aChannel, nsISupports *ctxt, nsresult aStatus, const PRUnichar* aMsg)
|
1999-06-06 00:21:27 +04:00
|
|
|
{
|
1999-07-29 04:42:25 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(ctxt, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
|
|
|
return aMsgUrl->SetUrlState(PR_FALSE, aStatus);
|
|
|
|
else
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
1999-06-06 00:21:27 +04:00
|
|
|
}
|
|
|
|
|
1999-06-23 07:29:44 +04:00
|
|
|
nsresult nsMsgProtocol::LoadUrl(nsIURI * aURL, nsISupports * /* aConsumer */)
|
1999-06-06 00:21:27 +04:00
|
|
|
{
|
|
|
|
// okay now kick us off to the next state...
|
|
|
|
// our first state is a process state so drive the state machine...
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(aURL);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK); // set the url as a url currently being run...
|
1999-07-29 04:42:25 +04:00
|
|
|
|
|
|
|
if (!m_socketIsOpen)
|
|
|
|
{
|
|
|
|
// put us in a state where we are always notified of incoming data
|
|
|
|
m_channel->AsyncRead(m_startPosition, m_readCount, aURL,this /* stream observer */);
|
|
|
|
m_socketIsOpen = PR_TRUE; // mark the channel as open
|
|
|
|
} // if we got an event queue service
|
1999-06-06 00:21:27 +04:00
|
|
|
else // the connection is already open so we should begin processing our new url...
|
1999-07-29 04:42:25 +04:00
|
|
|
rv = ProcessProtocolState(aURL, nsnull, 0, 0);
|
1999-06-06 00:21:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|