зеркало из https://github.com/mozilla/pjs.git
Nntp test harness and associated stub files....
This commit is contained in:
Родитель
846bb23626
Коммит
c7cc85cb3d
|
@ -0,0 +1,648 @@
|
|||
/* -*- 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.
|
||||
*/
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
* This test program is designed to test netlib's implementation of nsITransport.
|
||||
* In particular, it is currently geared towards testing their socket implemnation.
|
||||
* When the test program starts up, you are prompted for a port and domain
|
||||
* (I may have these hard coded right now to be nsmail-2 and port 143).
|
||||
* After entering this information, we'll build a connection to the host name.
|
||||
* You can then enter raw protocol text (i.e. "1 capability") and watch the data
|
||||
* that comes back from the socket. After data is returned, you can enter another
|
||||
* line of protocol.
|
||||
*===============================================================================*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef XP_PC
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "plstr.h"
|
||||
#include "plevent.h"
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsINetService.h"
|
||||
#include "nsRepository.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nntpCore.h"
|
||||
#include "nsNNTPProtocol.h"
|
||||
#include "nsNntpUrl.h"
|
||||
|
||||
// include the event sinks for the protocol you are testing
|
||||
#include "nsINNTPHost.h"
|
||||
|
||||
#include "nsINetService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsXPComCIID.h"
|
||||
|
||||
#ifdef XP_PC
|
||||
#define NETLIB_DLL "netlib.dll"
|
||||
#define XPCOM_DLL "xpcom32.dll"
|
||||
#else
|
||||
#ifdef XP_MAC
|
||||
#include "nsMacRepository.h"
|
||||
#else
|
||||
#define NETLIB_DLL "libnetlib.so"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Define keys for all of the interfaces we are going to require for this test
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
static NS_DEFINE_IID(kNetServiceCID, NS_NETSERVICE_CID);
|
||||
static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
static NS_DEFINE_IID(kIInputStreamIID, NS_IINPUTSTREAM_IID);
|
||||
static NS_DEFINE_IID(kIURLIID, NS_IURL_IID);
|
||||
static NS_DEFINE_IID(kINntpUrlIID, NS_INNTPURL_IID);
|
||||
|
||||
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Define default values to be used to drive the test
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DEFAULT_HOST "zia.mcom.com"
|
||||
#define DEFAULT_PORT NEWS_PORT /* we get this value from nntpCore.h */
|
||||
#define DEFAULT_URL_TYPE "sockstub://" /* do NOT change this value until netlib re-write is done...*/
|
||||
|
||||
extern NET_StreamClass *MIME_MessageConverter(int format_out, void *closure,
|
||||
URL_Struct *url, MWContext *context);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// This function is used to load and prepare an nntp url which can be run by
|
||||
// a transport instance. For different protocols, you'll have different url
|
||||
// functions like this one in the test harness...
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
nsresult NS_NewNntpUrl(nsINntpUrl ** aResult, const nsString urlSpec)
|
||||
{
|
||||
nsIURL * pUrl = NULL;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsNntpUrl * nntpUrl = new nsNntpUrl(nsnull, nsnull);
|
||||
if (nntpUrl)
|
||||
{
|
||||
nntpUrl->ParseURL(urlSpec); // load the spec we were given...
|
||||
rv = nntpUrl->QueryInterface(kINntpUrlIID, (void **) aResult);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// temporary hack...we don't have escape search url in the new world yet....
|
||||
char *MSG_EscapeSearchUrl (const char *nntpCommand)
|
||||
{
|
||||
char *result = NULL;
|
||||
// max escaped length is two extra characters for every character in the cmd.
|
||||
char *scratchBuf = (char*) PR_Malloc (3*PL_strlen(nntpCommand) + 1);
|
||||
if (scratchBuf)
|
||||
{
|
||||
char *scratchPtr = scratchBuf;
|
||||
while (1)
|
||||
{
|
||||
char ch = *nntpCommand++;
|
||||
if (!ch)
|
||||
break;
|
||||
if (ch == '#' || ch == '?' || ch == '@' || ch == '\\')
|
||||
{
|
||||
*scratchPtr++ = '\\';
|
||||
sprintf (scratchPtr, "%X", ch);
|
||||
scratchPtr += 2;
|
||||
}
|
||||
else
|
||||
*scratchPtr++ = ch;
|
||||
}
|
||||
*scratchPtr = '\0';
|
||||
result = PL_strdup (scratchBuf); // realloc down to smaller size
|
||||
PR_Free(scratchBuf);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// The nsNntpTestDriver is a class that I envision could be generalized to form the
|
||||
// building block of a protocol test harness. To configure it, you would list all of
|
||||
// the events you know how to handle and when one of those events is triggered, you
|
||||
// would be asked to process it....right now it is just NNTP specific....
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsNntpTestDriver
|
||||
{
|
||||
public:
|
||||
nsNntpTestDriver(nsINetService * pService);
|
||||
virtual ~nsNntpTestDriver();
|
||||
|
||||
// run driver initializes the instance, lists the commands, runs the command and when
|
||||
// the command is finished, it reads in the next command and continues...theoretically,
|
||||
// the client should only ever have to call RunDriver(). It should do the rest of the
|
||||
// work....
|
||||
nsresult RunDriver();
|
||||
|
||||
// User drive commands
|
||||
void InitializeTestDriver(); // will end up prompting the user for things like host, port, etc.
|
||||
nsresult ListCommands(); // will list all available commands to the user...i.e. "get groups, get article, etc."
|
||||
nsresult ReadAndDispatchCommand(); // reads a command number in from the user and calls the appropriate command generator
|
||||
nsresult PromptForUserDataAndBuildUrl(const char * userPrompt);
|
||||
|
||||
// The following are event generators. They convert all of the available user commands into
|
||||
// URLs and then run the urls.
|
||||
nsresult OnListAllGroups(); // lists all the groups on the host
|
||||
nsresult OnListIDs();
|
||||
nsresult OnGetGroup(); // lists the status of the user specified group...
|
||||
nsresult OnListArticle();
|
||||
nsresult OnSearch();
|
||||
nsresult OnExit();
|
||||
protected:
|
||||
char m_urlSpec[200]; // "sockstub://hostname:port" it does not include the command specific data...
|
||||
char m_urlString[500]; // string representing the current url being run. Includes host AND command specific data.
|
||||
char m_userData[250]; // generic string buffer for storing the current user entered data...
|
||||
|
||||
// host and port info...
|
||||
PRUint32 m_port;
|
||||
char m_host[200];
|
||||
|
||||
nsINntpUrl * m_url;
|
||||
nsNNTPProtocol * m_nntpProtocol; // running protocol instance
|
||||
nsITransport * m_transport; // a handle on the current transport object being used with the protocol binding...
|
||||
|
||||
PRBool m_runningURL; // are we currently running a url? this flag is set to false on exit...
|
||||
|
||||
void InitializeProtocol(const char * urlSpec);
|
||||
PRBool m_protocolInitialized;
|
||||
};
|
||||
|
||||
nsNntpTestDriver::nsNntpTestDriver(nsINetService * pNetService)
|
||||
{
|
||||
m_urlSpec[0] = '\0';
|
||||
m_urlString[0] = '\0';
|
||||
m_url = nsnull;
|
||||
m_protocolInitialized = PR_FALSE;
|
||||
m_runningURL = PR_TRUE;
|
||||
|
||||
InitializeTestDriver(); // prompts user for initialization information...
|
||||
|
||||
// create a transport socket...
|
||||
pNetService->CreateSocketTransport(&m_transport, m_port, m_host);
|
||||
m_nntpProtocol = nsnull; // we can't create it until we have a url...
|
||||
}
|
||||
|
||||
void nsNntpTestDriver::InitializeProtocol(const char * urlString)
|
||||
{
|
||||
// this is called when we don't have a url nor a protocol instance yet...
|
||||
NS_NewNntpUrl(&m_url, urlString);
|
||||
// now create a protocl instance...
|
||||
m_nntpProtocol = new nsNNTPProtocol(m_url, m_transport);
|
||||
m_protocolInitialized = PR_TRUE;
|
||||
}
|
||||
|
||||
nsNntpTestDriver::~nsNntpTestDriver()
|
||||
{
|
||||
NS_IF_RELEASE(m_url);
|
||||
NS_IF_RELEASE(m_transport);
|
||||
delete m_nntpProtocol;
|
||||
}
|
||||
|
||||
nsresult nsNntpTestDriver::RunDriver()
|
||||
{
|
||||
nsresult status = NS_OK;
|
||||
|
||||
while (m_runningURL)
|
||||
{
|
||||
// if we haven't gotten started (and created a protocol) or
|
||||
// if the protocol instance is currently not busy, then read in a new command
|
||||
// and process it...
|
||||
if ((!m_nntpProtocol) || m_nntpProtocol->IsRunningUrl() == PR_FALSE) // if we aren't running the url anymore, ask ueser for another command....
|
||||
{
|
||||
status = ReadAndDispatchCommand();
|
||||
} // if running url
|
||||
#ifdef XP_PC
|
||||
MSG msg;
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // until the user has stopped running the url (which is really the test session.....
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void nsNntpTestDriver::InitializeTestDriver()
|
||||
{
|
||||
// prompt the user for port and host name
|
||||
char portString[20]; // used to read in the port string
|
||||
char hostString[200];
|
||||
portString[0] = '\0';
|
||||
hostString[0] = '\0';
|
||||
m_host[0] = '\0';
|
||||
m_port = DEFAULT_PORT;
|
||||
|
||||
// load default host name and set the start of the url
|
||||
PL_strcpy(m_host, DEFAULT_HOST);
|
||||
PL_strcpy(m_urlSpec, DEFAULT_URL_TYPE); // copy "sockstub://" part into url spec...
|
||||
|
||||
// prompt user for port...
|
||||
printf("Enter port to use [%d]: ", m_port);
|
||||
scanf("%[^\n]", portString);
|
||||
if (portString && *portString)
|
||||
{
|
||||
m_port = atoi(portString);
|
||||
}
|
||||
scanf("%c", portString); // eat the extra CR
|
||||
|
||||
// now prompt for the host name....
|
||||
printf("Enter host name to use [%s]: ", m_host);
|
||||
scanf("%[^\n]", hostString);
|
||||
scanf("%c", portString); // eat the extra CR
|
||||
if(hostString && *hostString)
|
||||
{
|
||||
PL_strcpy(m_host, hostString);
|
||||
}
|
||||
|
||||
PL_strcat(m_urlSpec, m_host);
|
||||
// we'll actually build the url (spec + user data) once the user has specified a command they want to try...
|
||||
}
|
||||
|
||||
// prints the userPrompt and then reads in the user data. Assumes urlData has already been allocated.
|
||||
// it also reconstructs the url string in m_urlString but does NOT reload it....
|
||||
nsresult nsNntpTestDriver::PromptForUserDataAndBuildUrl(const char * userPrompt)
|
||||
{
|
||||
char tempBuffer[500];
|
||||
tempBuffer[0] = '\0';
|
||||
|
||||
if (userPrompt && *userPrompt)
|
||||
printf(userPrompt);
|
||||
else
|
||||
printf("Enter data for command: ");
|
||||
|
||||
scanf("%[^\n]", tempBuffer);
|
||||
if (*tempBuffer)
|
||||
{
|
||||
if (tempBuffer[0]) // kill off any CR or LFs...
|
||||
{
|
||||
PRUint32 length = PL_strlen(tempBuffer);
|
||||
if (length > 0 && tempBuffer[length-1] == '\r')
|
||||
tempBuffer[length-1] = '\0';
|
||||
|
||||
// okay, user gave us a valid line so copy it into the user data field..o.t. leave user
|
||||
// data field untouched. This allows us to use default values for things...
|
||||
m_userData[0] = '\0';
|
||||
PL_strcpy(m_userData, tempBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
char buffer[2];
|
||||
scanf("%c", buffer); // eat up the CR that is still in the input stream...
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNntpTestDriver::ReadAndDispatchCommand()
|
||||
{
|
||||
nsresult status = NS_OK;
|
||||
PRInt32 command = 0;
|
||||
char commandString[5];
|
||||
commandString[0] = '\0';
|
||||
|
||||
printf("Enter command number: ");
|
||||
scanf("%[^\n]", commandString);
|
||||
if (commandString && *commandString)
|
||||
{
|
||||
command = atoi(commandString);
|
||||
}
|
||||
scanf("%c", commandString); // eat the extra CR
|
||||
|
||||
// now switch on command to the appropriate
|
||||
switch (command)
|
||||
{
|
||||
case 0:
|
||||
status = ListCommands();
|
||||
break;
|
||||
case 1:
|
||||
status = OnListAllGroups();
|
||||
break;
|
||||
case 2:
|
||||
status = OnGetGroup();
|
||||
break;
|
||||
case 3:
|
||||
status = OnListIDs();
|
||||
break;
|
||||
case 4:
|
||||
status = OnListArticle();
|
||||
break;
|
||||
case 5:
|
||||
status = OnSearch();
|
||||
break;
|
||||
default:
|
||||
status = OnExit();
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
nsresult nsNntpTestDriver::ListCommands()
|
||||
{
|
||||
printf("Commands currently available: \n");
|
||||
printf("0) List available commands. \n");
|
||||
printf("1) List all news groups. \n");
|
||||
printf("2) Get (and subscribe) to a group. \n");
|
||||
printf("3) List ids. \n");
|
||||
printf("4) Get an article. \n");
|
||||
printf("5) Perform Search. \n");
|
||||
printf("9) Exit the test application. \n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin protocol specific command url generation code...gee that's a mouthful....
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult nsNntpTestDriver::OnExit()
|
||||
{
|
||||
printf("Terminating NNTP test harness....\n");
|
||||
m_runningURL = PR_FALSE; // next time through the test driver loop, we'll kick out....
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsNntpTestDriver::OnListAllGroups()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// no prompt for url data....just append a '*' to the url data and run it...
|
||||
m_urlString[0] = '\0';
|
||||
PL_strcpy(m_urlString, m_urlSpec);
|
||||
PL_strcat(m_urlString, "/");
|
||||
PL_strcat(m_urlString, "*");
|
||||
|
||||
if (m_protocolInitialized == PR_FALSE)
|
||||
InitializeProtocol(m_urlString);
|
||||
|
||||
m_url->SetSpec(m_urlString); // reset spec
|
||||
rv = m_nntpProtocol->LoadURL(m_url);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsNntpTestDriver::OnListIDs()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// no prompt for url data....just append a '*' to the url data and run it...
|
||||
m_urlString[0] = '\0';
|
||||
PL_strcpy(m_urlString, m_urlSpec);
|
||||
PL_strcat(m_urlString, "/");
|
||||
|
||||
|
||||
rv = PromptForUserDataAndBuildUrl("Group to fetch IDs for: ");
|
||||
PL_strcat(m_urlString, m_userData);
|
||||
PL_strcat(m_urlString, "?list-ids");
|
||||
|
||||
if (m_protocolInitialized == PR_FALSE)
|
||||
InitializeProtocol(m_urlString);
|
||||
else
|
||||
rv = m_url->SetSpec(m_urlString); // reset spec
|
||||
|
||||
// load the correct newsgroup interface as an event sink...
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
// before we re-load, assume it is a group command and configure our nntpurl correctly...
|
||||
nsINNTPHost * host = nsnull;
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
nsINNTPNewsgroupList * list = nsnull;
|
||||
rv = m_url->GetNntpHost(&host);
|
||||
if (host)
|
||||
{
|
||||
rv = host->FindGroup(m_userData, &group);
|
||||
if (group)
|
||||
group->GetNewsgroupList(&list);
|
||||
|
||||
rv = m_url->SetNewsgroup(group);
|
||||
rv = m_url->SetNewsgroupList(list);
|
||||
NS_IF_RELEASE(group);
|
||||
NS_IF_RELEASE(list);
|
||||
NS_IF_RELEASE(host);
|
||||
}
|
||||
|
||||
rv = m_nntpProtocol->LoadURL(m_url);
|
||||
} // if user provided the data...
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsNntpTestDriver::OnListArticle()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// first, prompt the user for the name of the group to fetch
|
||||
// prime article number with a default value...
|
||||
m_userData[0] = '\0';
|
||||
PL_strcpy(m_userData, "35D8A048.3C0F0C7A@zia.mcom.com");
|
||||
rv = PromptForUserDataAndBuildUrl("Article Number to Fetch: ");
|
||||
// no prompt for url data....just append a '*' to the url data and run it...
|
||||
m_urlString[0] = '\0';
|
||||
PL_strcpy(m_urlString, m_urlSpec);
|
||||
PL_strcat(m_urlString, "/");
|
||||
PL_strcat(m_urlString, m_userData);
|
||||
|
||||
if (m_protocolInitialized == PR_FALSE)
|
||||
InitializeProtocol(m_urlString);
|
||||
else
|
||||
m_url->SetSpec(m_urlString); // reset spec
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
// before we re-load, assume it is a group command and configure our nntpurl correctly...
|
||||
nsINNTPHost * host = nsnull;
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
nsINNTPNewsgroupList * list = nsnull;
|
||||
|
||||
rv = PromptForUserDataAndBuildUrl("Group article is in: ");
|
||||
rv = m_url->GetNntpHost(&host);
|
||||
if (host)
|
||||
{
|
||||
rv = host->FindGroup(m_userData, &group);
|
||||
if (group)
|
||||
group->GetNewsgroupList(&list);
|
||||
|
||||
rv = m_url->SetNewsgroup(group);
|
||||
rv = m_url->SetNewsgroupList(list);
|
||||
NS_IF_RELEASE(group);
|
||||
NS_IF_RELEASE(list);
|
||||
NS_IF_RELEASE(host);
|
||||
}
|
||||
|
||||
rv = m_nntpProtocol->LoadURL(m_url);
|
||||
} // if user provided the data...
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsNntpTestDriver::OnSearch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// first, prompt the user for the name of the group to fetch
|
||||
rv = PromptForUserDataAndBuildUrl("Group to search: ");
|
||||
m_urlString[0] = '\0';
|
||||
PL_strcpy(m_urlString, m_urlSpec);
|
||||
PL_strcat(m_urlString, "/");
|
||||
PL_strcat(m_urlString, m_userData);
|
||||
|
||||
// now append "?search" to the end...
|
||||
PL_strcat(m_urlString, "?search/");
|
||||
rv = PromptForUserDataAndBuildUrl("Search criteria: ");
|
||||
if (m_userData[0]) // did the user enter in something???
|
||||
{
|
||||
char * escapedBuffer = MSG_EscapeSearchUrl(m_userData);
|
||||
PL_strcat(m_urlString, escapedBuffer);
|
||||
}
|
||||
|
||||
if (m_protocolInitialized == PR_FALSE)
|
||||
InitializeProtocol(m_urlString);
|
||||
else
|
||||
m_url->SetSpec(m_urlString); // reset spec
|
||||
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
// before we re-load, assume it is a group command and configure our nntpurl correctly...
|
||||
nsINNTPHost * host = nsnull;
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
nsINNTPNewsgroupList * list = nsnull;
|
||||
rv = m_url->GetNntpHost(&host);
|
||||
if (host)
|
||||
{
|
||||
rv = host->FindGroup(m_userData, &group);
|
||||
if (group)
|
||||
group->GetNewsgroupList(&list);
|
||||
|
||||
rv = m_url->SetNewsgroup(group);
|
||||
rv = m_url->SetNewsgroupList(list);
|
||||
NS_IF_RELEASE(group);
|
||||
NS_IF_RELEASE(list);
|
||||
NS_IF_RELEASE(host);
|
||||
}
|
||||
|
||||
rv = m_nntpProtocol->LoadURL(m_url);
|
||||
} // if user provided the data...
|
||||
|
||||
return rv;
|
||||
|
||||
|
||||
}
|
||||
nsresult nsNntpTestDriver::OnGetGroup()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// first, prompt the user for the name of the group to fetch
|
||||
rv = PromptForUserDataAndBuildUrl("Group to fetch: ");
|
||||
// no prompt for url data....just append a '*' to the url data and run it...
|
||||
m_urlString[0] = '\0';
|
||||
PL_strcpy(m_urlString, m_urlSpec);
|
||||
PL_strcat(m_urlString, "/");
|
||||
PL_strcat(m_urlString, m_userData);
|
||||
|
||||
if (m_protocolInitialized == PR_FALSE)
|
||||
InitializeProtocol(m_urlString);
|
||||
else
|
||||
m_url->SetSpec(m_urlString); // reset spec
|
||||
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
// before we re-load, assume it is a group command and configure our nntpurl correctly...
|
||||
nsINNTPHost * host = nsnull;
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
nsINNTPNewsgroupList * list = nsnull;
|
||||
rv = m_url->GetNntpHost(&host);
|
||||
if (host)
|
||||
{
|
||||
rv = host->FindGroup(m_userData, &group);
|
||||
if (group)
|
||||
group->GetNewsgroupList(&list);
|
||||
|
||||
rv = m_url->SetNewsgroup(group);
|
||||
rv = m_url->SetNewsgroupList(list);
|
||||
NS_IF_RELEASE(group);
|
||||
NS_IF_RELEASE(list);
|
||||
NS_IF_RELEASE(host);
|
||||
}
|
||||
|
||||
rv = m_nntpProtocol->LoadURL(m_url);
|
||||
} // if user provided the data...
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
nsINetService * pNetService;
|
||||
nsresult result;
|
||||
nsIURL * pURL = NULL;
|
||||
|
||||
PL_InitializeEventsLib("");
|
||||
nsRepository::RegisterFactory(kNetServiceCID, NETLIB_DLL, PR_FALSE, PR_FALSE);
|
||||
nsRepository::RegisterFactory(kEventQueueServiceCID, XPCOM_DLL, PR_FALSE, PR_FALSE);
|
||||
|
||||
// Create the Event Queue for this thread...
|
||||
nsIEventQueueService *pEventQService = nsnull;
|
||||
result = nsServiceManager::GetService(kEventQueueServiceCID,
|
||||
kIEventQueueServiceIID,
|
||||
(nsISupports **)&pEventQService);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// XXX: What if this fails?
|
||||
result = pEventQService->CreateThreadEventQueue();
|
||||
}
|
||||
|
||||
// ask the net lib service for a nsINetStream:
|
||||
result = NS_NewINetService(&pNetService, NULL);
|
||||
if (NS_FAILED(result) || !pNetService)
|
||||
{
|
||||
printf("unable to initialize net serivce. \n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// now register a mime converter....
|
||||
NET_RegisterContentTypeConverter (MESSAGE_RFC822, FO_NGLAYOUT, NULL, MIME_MessageConverter);
|
||||
NET_RegisterContentTypeConverter (MESSAGE_RFC822, FO_CACHE_AND_NGLAYOUT, NULL, MIME_MessageConverter);
|
||||
|
||||
// okay, everything is set up, now we just need to create a test driver and run it...
|
||||
nsNntpTestDriver * driver = new nsNntpTestDriver(pNetService);
|
||||
if (driver)
|
||||
{
|
||||
driver->RunDriver();
|
||||
// when it kicks out...it is done....so delete it...
|
||||
delete driver;
|
||||
}
|
||||
|
||||
// shut down:
|
||||
NS_RELEASE(pNetService);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* -*- 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.
|
||||
*/
|
||||
|
||||
/* This is a stub event sink for a NNTP Newsgroup introduced by mscott to test
|
||||
the NNTP protocol */
|
||||
|
||||
#include "nsISupports.h" /* interface nsISupports */
|
||||
#include "nsINNTPCategoryContainer.h"
|
||||
#include "nsINNTPNewsgroup.h" /* interface nsINNTPNewsgroup */
|
||||
|
||||
#include "nscore.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static NS_DEFINE_IID(kINNTPCategoryContainerIID, NS_INNTPCATEGORYCONTAINER_IID);
|
||||
|
||||
|
||||
class nsNNTPCategoryContainerStub : public nsISupports {
|
||||
public:
|
||||
nsNNTPCategoryContainerStub();
|
||||
virtual ~nsNNTPCategoryContainerStub();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_IMETHOD GetRootCategory(nsINNTPNewsgroup * *aRootCategory);
|
||||
NS_IMETHOD SetRootCategory(nsINNTPNewsgroup * aRootCategory);
|
||||
|
||||
protected:
|
||||
nsINNTPNewsgroup * m_newsgroup;
|
||||
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNNTPCategoryContainerStub, kINNTPCategoryContainerIID);
|
||||
|
||||
nsNNTPCategoryContainerStub::nsNNTPCategoryContainerStub()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_newsgroup = nsnull;
|
||||
}
|
||||
|
||||
nsNNTPCategoryContainerStub::~nsNNTPCategoryContainerStub()
|
||||
{
|
||||
printf("Destroying category container. \n");
|
||||
NS_IF_RELEASE(m_newsgroup);
|
||||
}
|
||||
|
||||
nsresult nsNNTPCategoryContainerStub::GetRootCategory(nsINNTPNewsgroup * *aRootCategory)
|
||||
{
|
||||
if (aRootCategory)
|
||||
{
|
||||
*aRootCategory = m_newsgroup;
|
||||
NS_IF_ADDREF(m_newsgroup);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsNNTPCategoryContainerStub::SetRootCategory(nsINNTPNewsgroup * aRootCategory)
|
||||
{
|
||||
if (aRootCategory)
|
||||
{
|
||||
char * name = nsnull;
|
||||
aRootCategory->GetName(&name);
|
||||
printf("Setting root category for container to %s", name ? name : "unspecified");
|
||||
m_newsgroup = aRootCategory;
|
||||
NS_IF_ADDREF(m_newsgroup);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
nsresult NS_NewCategoryContainerFromNewsgroup(nsINNTPCategoryContainer ** aInstancePtr, nsINNTPNewsgroup* group)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsNNTPCategoryContainerStub * stub = nsnull;
|
||||
if (aInstancePtr)
|
||||
{
|
||||
stub = new nsNNTPCategoryContainerStub();
|
||||
stub->SetRootCategory(group);
|
||||
rv = stub->QueryInterface(kINNTPCategoryContainerIID, (void **) aInstancePtr);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,693 @@
|
|||
/* -*- 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.
|
||||
*/
|
||||
|
||||
/* This is a stub event sink for a NNTP Host introduced by mscott to test
|
||||
the NNTP protocol */
|
||||
|
||||
#include "nsINNTPHost.h"
|
||||
#include "nscore.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsINNTPNewsgroup.h"
|
||||
|
||||
#include "nsMsgGroupRecord.h"
|
||||
#include "nsMsgPtrArray.h"
|
||||
#include "nsNNTPNewsgroupList.h"
|
||||
#include "nsNNTPNewsgroup.h"
|
||||
|
||||
static NS_DEFINE_IID(kINNTPHostIID, NS_INNTPHOST_IID);
|
||||
static NS_DEFINE_IID(kINNTPNewsgroupIID, NS_INNTPNEWSGROUP_IID);
|
||||
|
||||
class nsNNTPHostStub : public nsINNTPHost
|
||||
{
|
||||
public:
|
||||
nsNNTPHostStub(const char *name, PRInt32 port);
|
||||
|
||||
virtual ~nsNNTPHostStub();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINNTPHost
|
||||
|
||||
NS_IMETHOD GetSupportsExtensions(PRBool *aSupportsExtensions);
|
||||
NS_IMETHOD SetSupportsExtensions(PRBool aSupportsExtensions);
|
||||
|
||||
NS_IMETHOD AddExtension (const char *ext);
|
||||
NS_IMETHOD QueryExtension (const char *ext, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD GetPostingAllowed(PRBool * aPostingAllowed);
|
||||
NS_IMETHOD SetPostingAllowed(PRBool aPostingAllowed);
|
||||
|
||||
NS_IMETHOD GetPushAuth(PRBool *aPushAuth);
|
||||
NS_IMETHOD SetPushAuth(PRBool aPushAuth);
|
||||
|
||||
NS_IMPL_CLASS_GETSET(LastUpdatedTime, PRInt64, m_lastGroupUpdate);
|
||||
|
||||
NS_IMETHOD GetNewsgroupList(const char *groupname, nsINNTPNewsgroupList **_retval);
|
||||
|
||||
NS_IMETHOD GetNewsgroupAndNumberOfID(const char *message_id,
|
||||
nsINNTPNewsgroup **group,
|
||||
PRUint32 *messageNumber);
|
||||
|
||||
/* get this from MSG_Master::FindNewsFolder */
|
||||
NS_IMETHOD FindNewsgroup(const char *groupname, PRBool create,
|
||||
nsINNTPNewsgroup **_retval) { return FindGroup(groupname, _retval);}
|
||||
|
||||
NS_IMETHOD AddPropertyForGet (const char *property, const char *value);
|
||||
NS_IMETHOD QueryPropertyForGet (const char *property, char **_retval);
|
||||
|
||||
NS_IMETHOD AddSearchableGroup(const char *groupname);
|
||||
// should these go into interfaces?
|
||||
NS_IMETHOD QuerySearchableGroup (const char *group, PRBool *);
|
||||
//NS_IMETHOD QuerySearchableGroupCharsets(const char *group, char **);
|
||||
|
||||
// Virtual groups
|
||||
NS_IMETHOD AddVirtualGroup(const char *responseText) { return NS_OK;}
|
||||
NS_IMETHOD SetIsVirtualGroup(const char *groupname, PRBool isVirtual);
|
||||
NS_IMETHOD GetIsVirtualGroup(const char *groupname, PRBool *_retval);
|
||||
|
||||
// custom/searchable headers
|
||||
NS_IMETHOD AddSearchableHeader(const char *headerName);
|
||||
NS_IMETHOD QuerySearchableHeader(const char *headerName, PRBool *_retval);
|
||||
|
||||
// Go load the newsrc for this host. Creates the subscribed hosts as
|
||||
// children of the given nsIMsgFolder.
|
||||
NS_IMETHOD LoadNewsrc();
|
||||
|
||||
// Write out the newsrc for this host right now. In general, either
|
||||
// MarkDirty() or WriteIfDirty() should be called instead.
|
||||
NS_IMETHOD WriteNewsrc();
|
||||
|
||||
// Write out the newsrc for this host right now, if anything has changed
|
||||
// in it.
|
||||
NS_IMETHOD WriteIfDirty();
|
||||
|
||||
// Note that something has changed, and we need to rewrite the newsrc file
|
||||
// for this host at some point.
|
||||
NS_IMETHOD MarkDirty();
|
||||
|
||||
/* the Setter implementation is a little more complex */
|
||||
NS_IMPL_CLASS_GETTER(GetNewsRCFilename, char *, m_filename);
|
||||
NS_IMETHOD SetNewsRCFilename(char *);
|
||||
|
||||
|
||||
NS_IMETHOD FindGroup(const char* name, nsINNTPNewsgroup* *_retval);
|
||||
NS_IMETHOD AddGroup(const char *groupname,
|
||||
nsINNTPNewsgroup **retval);
|
||||
|
||||
//NS_IMETHOD AddGroup(const char *groupname,
|
||||
// nsMsgGroupRecord *groupRecord,
|
||||
// nsINNTPNewsgroup **retval);
|
||||
|
||||
NS_IMETHOD RemoveGroupByName(const char *groupName);
|
||||
NS_IMETHOD RemoveGroup(const nsINNTPNewsgroup*);
|
||||
|
||||
NS_IMETHOD AddNewNewsgroup(const char *groupName,
|
||||
PRInt32 first,
|
||||
PRInt32 last,
|
||||
const char *flags,
|
||||
PRBool xactiveFlags);
|
||||
|
||||
/* Name of directory to store newsgroup
|
||||
databases in. This needs to have
|
||||
"/groupname" appended to it, and the
|
||||
whole thing can be passed to the XP_File
|
||||
stuff with a type of xpXoverCache. */
|
||||
NS_IMETHOD GetDbDirName(char * *aDbDirName);
|
||||
|
||||
/* Returns a list of newsgroups. The result
|
||||
must be free'd using PR_Free(); the
|
||||
individual strings must not be free'd. */
|
||||
NS_IMETHOD GetGroupList(char **_retval);
|
||||
|
||||
NS_IMETHOD DisplaySubscribedGroup(const char *groupname,
|
||||
PRInt32 first_message,
|
||||
PRInt32 last_message,
|
||||
PRInt32 total_messages,
|
||||
PRBool visit_now);
|
||||
// end of nsINNTPHost
|
||||
|
||||
private:
|
||||
virtual PRBool IsNews () { return PR_TRUE; }
|
||||
virtual nsINNTPHost *GetNewsHost() { return this; }
|
||||
|
||||
// Get the nsIMsgFolder which represents this host; the children
|
||||
// of this nsIMsgFolder are the groups in this host.
|
||||
nsIMsgFolder* GetHostInfo() {return m_hostinfo;}
|
||||
|
||||
// GetNumGroupsNeedingCounts() returns how many newsgroups we have
|
||||
// that we don't have an accurate count of unread/total articles.
|
||||
NS_IMETHOD GetNumGroupsNeedingCounts(PRInt32 *);
|
||||
|
||||
// GetFirstGroupNeedingCounts() returns the name of the first newsgroup
|
||||
// that does not have an accurate count of unread/total articles. The
|
||||
// string must be free'd by the caller using PR_Free().
|
||||
NS_IMETHOD GetFirstGroupNeedingCounts(char **);
|
||||
|
||||
|
||||
// GetFirstGroupNeedingExtraInfo() returns the name of the first newsgroup
|
||||
// that does not have extra info (xactive flags and prettyname). The
|
||||
// string must be free'd by the caller using PR_Free().
|
||||
NS_IMETHOD GetFirstGroupNeedingExtraInfo(char **);
|
||||
|
||||
// Returns the pretty name for the given group. The resulting string
|
||||
// must be free'd using delete[].
|
||||
char* GetPrettyName(const char* groupname) { return m_prettyName;}
|
||||
NS_IMETHOD SetPrettyName(const char* groupname, const char* prettyname);
|
||||
|
||||
NS_IMETHOD SetGroupNeedsExtraInfo(const char *groupname, PRBool value);
|
||||
// Finds the container newsgroup for this category (or NULL if this isn't
|
||||
// a category). The resulting string must be free'd using delete[].
|
||||
char* GetCategoryContainer(const char* groupname, nsMsgGroupRecord *inGroupRecord = NULL);
|
||||
nsINNTPNewsgroup *GetCategoryContainerFolderInfo(const char *groupname);
|
||||
|
||||
|
||||
nsMsgGroupRecord* GetGroupTree() {return m_groupTree;}
|
||||
|
||||
NS_IMETHOD GroupNotFound(const char *groupName, PRBool opening);
|
||||
|
||||
protected:
|
||||
|
||||
char* m_hostname;
|
||||
char * m_prettyName;
|
||||
PRInt32 m_port;
|
||||
|
||||
nsISupportsArray *m_groups; // List of nsINNTPNewsgroup* objects.
|
||||
|
||||
nsIMsgFolder* m_hostinfo; // Object representing entire newshost in
|
||||
// tree.
|
||||
char* m_optionLines;
|
||||
|
||||
|
||||
char* m_filename; /* The name of the newsrc file associated with
|
||||
this host. This will be of the form:
|
||||
|
||||
"" meaning .newsrc or .snewsrc
|
||||
HOST meaning .newsrc-HOST
|
||||
HOST:PORT meaning .newsrc-HOST:PORT
|
||||
|
||||
Whether it begins with .newsrc or .snewsrc
|
||||
depends on a special property slot
|
||||
(we pass one of
|
||||
the types xpNewsRC or xpSNewsRC to xp_file.)
|
||||
|
||||
The reason this is not simply derived from
|
||||
the host_name and port slots is that it's
|
||||
not a 1:1 mapping; if the user has a file
|
||||
called "newsrc", we will use that for the
|
||||
default host (the "" name.) Likewise,
|
||||
".newsrc-H" and ".newsrc-H:119" are
|
||||
ambiguous.
|
||||
*/
|
||||
|
||||
char* m_dbfilename;
|
||||
PRBool m_dirty;
|
||||
PRBool m_supportsExtensions;
|
||||
PRBool m_everexpanded; // Whether the user ever opened up this
|
||||
// newshost this session.
|
||||
PRBool m_checkedForNew; // Whether we've checked for new newgroups
|
||||
// in this newshost this session.
|
||||
PRBool m_groupSucceeded; // Whether a group command has succeeded this
|
||||
// session, protect against server bustage
|
||||
// where it says no group exists.
|
||||
|
||||
XPPtrArray m_supportedExtensions;
|
||||
XPPtrArray m_searchableGroups;
|
||||
XPPtrArray m_searchableHeaders;
|
||||
XPPtrArray m_propertiesForGet;
|
||||
XPPtrArray m_valuesForGet;
|
||||
|
||||
PRBool m_postingAllowed;
|
||||
PRBool m_pushAuth; // PR_TRUE if we should volunteer authentication without a
|
||||
// challenge
|
||||
|
||||
nsMsgGroupRecord* m_groupTree; // Tree of groups we're remembering.
|
||||
PRInt64 m_lastGroupUpdate;
|
||||
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNNTPHostStub, kINNTPHostIID);
|
||||
|
||||
nsNNTPHostStub::nsNNTPHostStub(const char * name, PRInt32 port)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_supportsExtensions = PR_FALSE;
|
||||
m_postingAllowed = PR_FALSE;
|
||||
m_lastGroupUpdate = 0;
|
||||
NS_NewISupportsArray(&m_groups);
|
||||
}
|
||||
|
||||
nsNNTPHostStub::~nsNNTPHostStub()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetSupportsExtensions(PRBool *aSupportsExtensions)
|
||||
{
|
||||
printf("Supports Extensions: %s. \n", m_supportsExtensions ? "TRUE" : "FALSE");
|
||||
if (aSupportsExtensions)
|
||||
*aSupportsExtensions = m_supportsExtensions;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::SetSupportsExtensions(PRBool aSupportsExtensions)
|
||||
{
|
||||
m_supportsExtensions = aSupportsExtensions;
|
||||
printf("Setting supports extensions to: %s. \n", m_supportsExtensions ? "TRUE" : "FALSE");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsNNTPHostStub::AddExtension(const char * extension)
|
||||
{
|
||||
printf("Adding extension: %s. \n", extension ? extension : "invalid extension");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::QueryExtension(const char * extension, PRBool * aRetValue)
|
||||
{
|
||||
printf("Querying extension %s. \n", extension ? extension : "invalid extension");
|
||||
if (PL_strstr(extension, "SEARCH"))
|
||||
*aRetValue = PR_TRUE;
|
||||
else
|
||||
*aRetValue = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetPostingAllowed(PRBool * aPostingAllowed)
|
||||
{
|
||||
printf("Posting Allowed: %s. \n", m_postingAllowed ? "TRUE" : "FALSE");
|
||||
if (aPostingAllowed)
|
||||
*aPostingAllowed = m_postingAllowed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::SetPostingAllowed(PRBool aPostingAllowed)
|
||||
{
|
||||
m_postingAllowed = aPostingAllowed;
|
||||
printf("Setting posting allowed to: %s. \n", m_postingAllowed ? "TRUE" : "FALSE");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetPushAuth(PRBool * aPushAuth)
|
||||
{
|
||||
printf("Push Authentication: %s. \n", m_pushAuth ? "TRUE" : "FALSE");
|
||||
if (aPushAuth)
|
||||
*aPushAuth = m_pushAuth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::SetPushAuth(PRBool aPushAuth)
|
||||
{
|
||||
m_pushAuth = aPushAuth;
|
||||
printf("Setting push auth to: %s. \n", m_pushAuth ? "TRUE" : "FALSE");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsNNTPHostStub::AddPropertyForGet (const char *property, const char *value)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
|
||||
tmp = PL_strdup(property);
|
||||
if (tmp)
|
||||
m_propertiesForGet.Add (tmp);
|
||||
|
||||
tmp = PL_strdup(value);
|
||||
if (tmp)
|
||||
m_valuesForGet.Add (tmp);
|
||||
|
||||
printf("Adding property %s for value %s. \n", property, value);
|
||||
|
||||
// this is odd. do we need this return value?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::QueryPropertyForGet (const char *property, char **retval)
|
||||
{
|
||||
*retval=NULL;
|
||||
for (int i = 0; i < m_propertiesForGet.GetSize(); i++)
|
||||
if (!PL_strcasecmp(property, (const char *) m_propertiesForGet.GetAt(i))) {
|
||||
*retval = (char *)m_valuesForGet.GetAt(i);
|
||||
printf("Retrieving property %s for get. \n", *retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::AddSearchableGroup (const char *group)
|
||||
{
|
||||
PRBool searchableGroup;
|
||||
nsresult rv = QuerySearchableGroup(group, &searchableGroup);
|
||||
if (NS_SUCCEEDED(rv) && !searchableGroup)
|
||||
{
|
||||
char *ourGroup = PL_strdup (group);
|
||||
if (ourGroup)
|
||||
{
|
||||
// strip off character set spec
|
||||
char *space = PL_strchr(ourGroup, ' ');
|
||||
if (space)
|
||||
*space = '\0';
|
||||
|
||||
m_searchableGroups.Add(ourGroup);
|
||||
printf("Adding %s to list of searchable groups. \n", ourGroup);
|
||||
|
||||
space++; // walk over to the start of the charsets
|
||||
// Add the group -> charset association.
|
||||
// XP_Puthash(m_searchableGroupCharsets, ourGroup, space);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::QuerySearchableGroup (const char *group, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
for (int i = 0; i < m_searchableGroups.GetSize(); i++)
|
||||
{
|
||||
const char *searchableGroup = (const char*) m_searchableGroups.GetAt(i);
|
||||
char *starInSearchableGroup = NULL;
|
||||
|
||||
if (!PL_strcmp(searchableGroup, "*")) {
|
||||
*_retval = PR_TRUE; // everything is searchable
|
||||
return NS_OK;
|
||||
}
|
||||
else if (NULL != (starInSearchableGroup = PL_strchr(searchableGroup, '*')))
|
||||
{
|
||||
if (!PL_strncasecmp(group, searchableGroup, PL_strlen(searchableGroup)-2)) {
|
||||
*_retval = PR_TRUE; // this group is in a searchable hierarchy
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (!PL_strcasecmp(group, searchableGroup)) {
|
||||
*_retval = PR_TRUE; // this group is individually searchable
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::SetIsVirtualGroup(const char * groupname, PRBool isVirtual)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetIsVirtualGroup(const char * groupname, PRBool * isVirtual)
|
||||
{
|
||||
*isVirtual = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::AddSearchableHeader (const char *header)
|
||||
{
|
||||
PRBool searchable;
|
||||
nsresult rv = QuerySearchableHeader(header, &searchable);
|
||||
if (NS_SUCCEEDED(rv) && searchable)
|
||||
{
|
||||
char *ourHeader = PL_strdup(header);
|
||||
if (ourHeader)
|
||||
m_searchableHeaders.Add(ourHeader);
|
||||
|
||||
printf("Added %s as a searchable header. \n", ourHeader);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::QuerySearchableHeader(const char *header, PRBool *retval)
|
||||
{
|
||||
*retval=PR_FALSE;
|
||||
for (int i = 0; i < m_searchableHeaders.GetSize(); i++)
|
||||
if (!PL_strncasecmp(header, (char*) m_searchableHeaders.GetAt(i), PL_strlen(header))) {
|
||||
*retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GroupNotFound(const char *groupName, PRBool opening)
|
||||
{
|
||||
printf("Group %s not found. \n", groupName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::AddNewNewsgroup(const char *groupName,
|
||||
PRInt32 first,
|
||||
PRInt32 last,
|
||||
const char *flags,
|
||||
PRBool xactiveFlags)
|
||||
{
|
||||
printf ("Adding new newsgroup: %s. \n", groupName);
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
AddGroup(groupName, &group);
|
||||
NS_IF_RELEASE(group); // we don't care about it...
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetNumGroupsNeedingCounts(PRInt32 * aNumGroups)
|
||||
{
|
||||
printf("Getting number of groups needing counts. \n");
|
||||
*aNumGroups = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetFirstGroupNeedingCounts(char ** aFirstGroup)
|
||||
{
|
||||
*aFirstGroup = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::DisplaySubscribedGroup(const char * groupname, PRInt32 first_message, PRInt32 last_message, PRInt32 total_messages,
|
||||
PRBool visit_now)
|
||||
{
|
||||
printf("Displaying subscribed group %s which has %d total messages. \n", groupname, total_messages);
|
||||
|
||||
nsresult rv;
|
||||
nsINNTPNewsgroup *newsgroup=NULL;
|
||||
|
||||
|
||||
rv = FindGroup(groupname, &newsgroup);
|
||||
|
||||
// SetGroupSucceeded(TRUE);
|
||||
if (!newsgroup && visit_now) // let's try autosubscribe...
|
||||
{
|
||||
rv = AddGroup(groupname, &newsgroup);
|
||||
}
|
||||
|
||||
if (!newsgroup)
|
||||
return NS_OK;
|
||||
else
|
||||
{
|
||||
PRBool subscribed;
|
||||
newsgroup->GetSubscribed(&subscribed);
|
||||
if (!subscribed)
|
||||
newsgroup->SetSubscribed(PR_TRUE);
|
||||
}
|
||||
|
||||
if (!newsgroup) return NS_OK;
|
||||
newsgroup->UpdateSummaryFromNNTPInfo(first_message, last_message,
|
||||
total_messages);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetFirstGroupNeedingExtraInfo(char ** retval)
|
||||
{
|
||||
if (retval)
|
||||
*retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::SetGroupNeedsExtraInfo(const char * groupName, PRBool needsExtraInfo)
|
||||
{
|
||||
printf("Setting group %s to need extra info.\n", groupName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetNewsgroupAndNumberOfID(const char *messageID, nsINNTPNewsgroup ** group, PRUint32 * messageNumber)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::SetPrettyName(const char * groupname, const char * prettyname)
|
||||
{
|
||||
printf("Setting group %s to have pretty name %s. \n", groupname, prettyname);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::LoadNewsrc()
|
||||
{
|
||||
printf("Loading newsrc....\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::WriteNewsrc()
|
||||
{
|
||||
printf("Writing out newsrc ...\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::WriteIfDirty()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::MarkDirty()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
nsresult nsNNTPHostStub::GetNewsRCFilename(char ** aNewsRCFileName)
|
||||
{
|
||||
if (aNewsRCFileName)
|
||||
*aNewsRCFileName = "temp.rc";
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult nsNNTPHostStub::SetNewsRCFilename(char * fileName)
|
||||
{
|
||||
printf ("Setting newsrc file name to %s\n.", fileName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetNewsgroupList(const char *groupname, nsINNTPNewsgroupList **_retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// find group with the group name...
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
rv = FindGroup(groupname, &group);
|
||||
if (group)
|
||||
{
|
||||
rv = group->GetNewsgroupList(_retval);
|
||||
NS_RELEASE(group);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::FindGroup(const char * name, nsINNTPNewsgroup ** retVal)
|
||||
{
|
||||
PRBool found = PR_FALSE;
|
||||
*retVal = nsnull;
|
||||
printf ("Looking up group %s.\n", name);
|
||||
for (PRInt32 count = 0; count < m_groups->Count() && !found; count++)
|
||||
{
|
||||
nsISupports * elem = m_groups->ElementAt(count);
|
||||
if (elem)
|
||||
{
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
elem->QueryInterface(kINNTPNewsgroupIID, (void **) &group);
|
||||
if (group)
|
||||
{
|
||||
char * groupName = nsnull;
|
||||
group->GetName(&groupName);
|
||||
if (groupName && PL_strcmp(name, groupName) == 0)
|
||||
{
|
||||
found = PR_TRUE;
|
||||
*retVal = group;
|
||||
NS_ADDREF(group);
|
||||
}
|
||||
|
||||
PR_FREEIF(groupName);
|
||||
NS_RELEASE(group);
|
||||
} // if group
|
||||
NS_RELEASE(elem);
|
||||
} // if elem
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::AddGroup(const char *groupname, nsINNTPNewsgroup **retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
printf ("Adding group %s to host.\n", groupname);
|
||||
// turn the group name into a new news group and create a newsgroup list for it as well...
|
||||
nsINNTPNewsgroup * group = nsnull;
|
||||
rv = NS_NewNewsgroup(&group, nsnull, /* nsNNTPArticleSet * */ nsnull, PR_TRUE, this, 0);
|
||||
if (group) // set the name for our group..
|
||||
group->SetName((char *) groupname);
|
||||
// generate a news group list for the new group...
|
||||
nsINNTPNewsgroupList * list = nsnull;
|
||||
rv = NS_NewNewsgroupList(&list,this, group);
|
||||
// now bind the group list to the group....
|
||||
if (list)
|
||||
{
|
||||
group->SetNewsgroupList(list);
|
||||
NS_RELEASE(list);
|
||||
}
|
||||
|
||||
// now add this group to our global list...
|
||||
m_groups->AppendElement(group);
|
||||
|
||||
if (retval)
|
||||
{
|
||||
*retval = group;
|
||||
NS_IF_ADDREF(group);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::RemoveGroup(const nsINNTPNewsgroup * group)
|
||||
{
|
||||
char * name = nsnull;
|
||||
group->GetName(&name);
|
||||
|
||||
printf ("Removing group %s.\n", name ? name : "unspecified");
|
||||
PR_FREEIF(name);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::RemoveGroupByName(const char *groupName)
|
||||
{
|
||||
printf ("Removing group %s. \n", groupName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetDbDirName(char ** aDirName)
|
||||
{
|
||||
if (aDirName)
|
||||
*aDirName = "temp.db";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPHostStub::GetGroupList(char ** retVal)
|
||||
{
|
||||
if (retVal)
|
||||
*retVal = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C"{
|
||||
|
||||
nsresult NS_NewNNTPHost(nsINNTPHost ** aInstancePtr, const char * name, PRUint32 port)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aInstancePtr)
|
||||
{
|
||||
nsNNTPHostStub * host = new nsNNTPHostStub(name, port);
|
||||
if (host)
|
||||
rv =host->QueryInterface(kINNTPHostIID, (void **) aInstancePtr);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,366 @@
|
|||
/* -*- 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.
|
||||
*/
|
||||
|
||||
/* This is a stub event sink for a NNTP Newsgroup introduced by mscott to test
|
||||
the NNTP protocol */
|
||||
|
||||
#include "nscore.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prmem.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsISupports.h" /* interface nsISupports */
|
||||
|
||||
#include "nsINNTPNewsgroup.h"
|
||||
#include "nsINNTPNewsgroupList.h"
|
||||
#include "nsNNTPArticleSet.h"
|
||||
#include "nsNNTPNewsgroupList.h"
|
||||
|
||||
/* temporary hack until MessageKey is defined */
|
||||
typedef PRUint32 MessageKey;
|
||||
|
||||
static NS_DEFINE_IID(kINNTPNewsgroupListIID, NS_INNTPNEWSGROUPLIST_IID);
|
||||
|
||||
class nsNNTPNewsgroupListStub : public nsINNTPNewsgroupList {
|
||||
|
||||
public:
|
||||
nsNNTPNewsgroupListStub(nsINNTPHost * host, nsINNTPNewsgroup * newsgroup);
|
||||
virtual ~nsNNTPNewsgroupListStub();
|
||||
|
||||
NS_DECL_ISUPPORTS;
|
||||
|
||||
NS_IMETHOD GetRangeOfArtsToDownload(PRInt32 first_message, PRInt32 last_message, PRInt32 maxextra, PRInt32 *real_first_message,
|
||||
PRInt32 *real_last_message, PRInt32 *_retval);
|
||||
|
||||
NS_IMETHOD AddToKnownArticles(PRInt32 first_message, PRInt32 last_message);
|
||||
|
||||
NS_IMETHOD InitXOVER(PRInt32 first_message, PRInt32 last_message);
|
||||
|
||||
NS_IMETHOD ProcessXOVER(const char *line, PRInt32 *status);
|
||||
|
||||
NS_IMETHOD ProcessNonXOVER(const char *line);
|
||||
NS_IMETHOD ResetXOVER();
|
||||
|
||||
NS_IMETHOD FinishXOVER(PRInt32 status, PRInt32 *newstatus);
|
||||
NS_IMETHOD ClearXOVERState();
|
||||
protected:
|
||||
NS_METHOD Init(nsINNTPHost *, nsINNTPNewsgroup*);
|
||||
|
||||
PRBool m_finishingXover;
|
||||
nsINNTPHost* GetHost() {return m_host;}
|
||||
const char * GetGroupName() {return m_groupName;}
|
||||
|
||||
PRBool m_startedUpdate;
|
||||
PRBool m_getOldMessages;
|
||||
PRBool m_promptedAlready;
|
||||
PRBool m_downloadAll;
|
||||
PRInt32 m_maxArticles;
|
||||
char *m_groupName;
|
||||
nsINNTPHost *m_host;
|
||||
nsINNTPNewsgroup * m_group;
|
||||
|
||||
MessageKey m_lastProcessedNumber;
|
||||
MessageKey m_firstMsgNumber;
|
||||
MessageKey m_lastMsgNumber;
|
||||
PRInt32 m_firstMsgToDownload;
|
||||
PRInt32 m_lastMsgToDownload;
|
||||
|
||||
struct MSG_NewsKnown m_knownArts;
|
||||
nsNNTPArticleSet *m_set;
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNNTPNewsgroupListStub, kINNTPNewsgroupListIID);
|
||||
|
||||
nsNNTPNewsgroupListStub::nsNNTPNewsgroupListStub(nsINNTPHost* host,
|
||||
nsINNTPNewsgroup *newsgroup)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
Init(host, newsgroup);
|
||||
}
|
||||
|
||||
|
||||
nsNNTPNewsgroupListStub::~nsNNTPNewsgroupListStub()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::Init(nsINNTPHost * host, nsINNTPNewsgroup * newsgroup)
|
||||
{
|
||||
m_group = newsgroup;
|
||||
NS_IF_ADDREF(newsgroup);
|
||||
|
||||
if (m_group)
|
||||
m_group->GetName(&m_groupName);
|
||||
|
||||
m_host = host;
|
||||
NS_IF_ADDREF(host);
|
||||
|
||||
m_lastProcessedNumber = 0;
|
||||
m_lastMsgNumber = 0;
|
||||
m_set = nsNNTPArticleSet::Create(host);
|
||||
m_finishingXover = PR_FALSE;
|
||||
m_startedUpdate = PR_FALSE;
|
||||
m_knownArts.host = nsnull;
|
||||
m_knownArts.set = m_set;
|
||||
m_knownArts.first_possible = 0;
|
||||
m_knownArts.last_possible = 0;
|
||||
m_knownArts.shouldGetOldest = PR_FALSE;
|
||||
m_knownArts.group_name = m_groupName;
|
||||
|
||||
m_knownArts.host = m_host;
|
||||
NS_IF_ADDREF(m_host);
|
||||
|
||||
m_getOldMessages = PR_FALSE;
|
||||
m_promptedAlready = PR_FALSE;
|
||||
m_downloadAll = PR_FALSE;
|
||||
m_maxArticles = 0;
|
||||
m_firstMsgToDownload = 0;
|
||||
m_lastMsgToDownload = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::GetRangeOfArtsToDownload(
|
||||
PRInt32 first_possible,
|
||||
PRInt32 last_possible,
|
||||
PRInt32 maxextra,
|
||||
PRInt32* first,
|
||||
PRInt32* last,
|
||||
PRInt32 *status)
|
||||
{
|
||||
PRBool emptyGroup_p = PR_FALSE;
|
||||
|
||||
if (!first || !last) return NS_ERROR_FAILURE;
|
||||
|
||||
*first = 0;
|
||||
*last = 0;
|
||||
|
||||
m_set->SetLastMember(last_possible); // make sure highwater mark is valid.
|
||||
|
||||
m_knownArts.first_possible = first_possible;
|
||||
m_knownArts.last_possible = last_possible;
|
||||
|
||||
/* Determine if we only want to get just new articles or more messages.
|
||||
If there are new articles at the end we haven't seen, we always want to get those first.
|
||||
Otherwise, we get the newest articles we haven't gotten, if we're getting more.
|
||||
My thought for now is that opening a newsgroup should only try to get new articles.
|
||||
Selecting "More Messages" will first try to get unseen messages, then old messages. */
|
||||
|
||||
if (m_getOldMessages || !m_knownArts.set->IsMember(last_possible))
|
||||
{
|
||||
|
||||
}
|
||||
m_firstMsgToDownload = *first;
|
||||
m_lastMsgToDownload = *last;
|
||||
if (status) *status=0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::AddToKnownArticles(PRInt32 first, PRInt32 last)
|
||||
{
|
||||
printf ("Adding articles %d to %d to known article set. \n", first, last);
|
||||
int status;
|
||||
// another temporary hack
|
||||
nsINNTPHost *host = m_knownArts.host;
|
||||
const char* group_name = m_knownArts.group_name;
|
||||
|
||||
if (m_knownArts.host != host ||
|
||||
m_knownArts.group_name == NULL ||
|
||||
PL_strcmp(m_knownArts.group_name, group_name) != 0 ||
|
||||
!m_knownArts.set)
|
||||
{
|
||||
m_knownArts.host = host;
|
||||
PR_FREEIF(m_knownArts.group_name);
|
||||
m_knownArts.group_name = PL_strdup(group_name);
|
||||
delete m_knownArts.set;
|
||||
m_knownArts.set = nsNNTPArticleSet::Create();
|
||||
|
||||
if (!m_knownArts.group_name || !m_knownArts.set) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
status = m_knownArts.set->AddRange(first, last);
|
||||
return status;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::InitXOVER(PRInt32 first_msg, PRInt32 last_msg)
|
||||
{
|
||||
|
||||
int status = 0;
|
||||
|
||||
/* Consistency checks, not that I know what to do if it fails (it will
|
||||
probably handle it OK...) */
|
||||
|
||||
/* If any XOVER lines from the last time failed to come in, mark those
|
||||
messages as read. */
|
||||
if (m_lastProcessedNumber < m_lastMsgNumber)
|
||||
{
|
||||
m_set->AddRange(m_lastProcessedNumber + 1, m_lastMsgNumber);
|
||||
}
|
||||
m_firstMsgNumber = first_msg;
|
||||
m_lastMsgNumber = last_msg;
|
||||
m_lastProcessedNumber = first_msg > 1 ? first_msg - 1 : 1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define NEWS_ART_DISPLAY_FREQ 10
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::ProcessXOVER(const char *line, int *status)
|
||||
{
|
||||
const char *next;
|
||||
PRUint32 message_number=0;
|
||||
// PRInt32 lines;
|
||||
PRBool read_p = PR_FALSE;
|
||||
|
||||
if (!line)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
next = line;
|
||||
|
||||
if (m_set && message_number > m_lastProcessedNumber + 1)
|
||||
{
|
||||
/* There are some articles that XOVER skipped; they must no longer
|
||||
exist. Mark them as read in the newsrc, so we don't include them
|
||||
next time in our estimated number of unread messages. */
|
||||
if (m_set->AddRange(m_lastProcessedNumber + 1, message_number - 1))
|
||||
{
|
||||
/* This isn't really an important enough change to warrant causing
|
||||
the newsrc file to be saved; we haven't gathered any information
|
||||
that won't also be gathered for free next time.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
m_lastProcessedNumber = message_number;
|
||||
if (m_knownArts.set)
|
||||
{
|
||||
int result = m_knownArts.set->Add(message_number);
|
||||
if (result < 0) {
|
||||
if (status) *status = result;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
if (message_number > m_lastMsgNumber)
|
||||
m_lastMsgNumber = message_number;
|
||||
else if (message_number < m_firstMsgNumber)
|
||||
m_firstMsgNumber = message_number;
|
||||
|
||||
if (m_set) {
|
||||
read_p = m_set->IsMember(message_number);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNNTPNewsgroupListStub::ResetXOVER()
|
||||
{
|
||||
printf("Resetting XOVER for newsgroup list. \n");
|
||||
m_lastMsgNumber = m_firstMsgNumber;
|
||||
m_lastProcessedNumber = m_lastMsgNumber;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When we don't have XOVER, but use HEAD, this is called instead.
|
||||
It reads lines until it has a whole header block, then parses the
|
||||
headers; then takes selected headers and creates an XOVER line
|
||||
from them. This is more for simplicity and code sharing than
|
||||
anything else; it means we end up parsing some things twice.
|
||||
But if we don't have XOVER, things are going to be so horribly
|
||||
slow anyway that this just doesn't matter.
|
||||
*/
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::ProcessNonXOVER (const char * /*line*/)
|
||||
{
|
||||
// ### dmb write me
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::FinishXOVER (int status, int *newstatus)
|
||||
{
|
||||
struct MSG_NewsKnown* k;
|
||||
|
||||
/* If any XOVER lines from the last time failed to come in, mark those
|
||||
messages as read. */
|
||||
|
||||
if (status >= 0 && m_lastProcessedNumber < m_lastMsgNumber)
|
||||
{
|
||||
m_set->AddRange(m_lastProcessedNumber + 1, m_lastMsgNumber);
|
||||
}
|
||||
|
||||
k = &m_knownArts;
|
||||
|
||||
if (k->set)
|
||||
{
|
||||
PRInt32 n = k->set->FirstNonMember();
|
||||
if (n < k->first_possible || n > k->last_possible)
|
||||
{
|
||||
/* We know we've gotten all there is to know. Take advantage of that to
|
||||
update our counts... */
|
||||
// ### dmb
|
||||
}
|
||||
}
|
||||
|
||||
if (m_finishingXover)
|
||||
{
|
||||
// turn on m_finishingXover - this is a horrible hack to avoid recursive
|
||||
// calls which happen when the fe selects a message as a result of getting EndingUpdate,
|
||||
// which interrupts this url right before it was going to finish and causes FinishXOver
|
||||
// to get called again.
|
||||
m_finishingXover = PR_TRUE;
|
||||
// if we haven't started an update, start one so the fe
|
||||
// will know to update the size of the view.
|
||||
if (!m_startedUpdate)
|
||||
{
|
||||
m_startedUpdate = PR_TRUE;
|
||||
}
|
||||
m_startedUpdate = PR_FALSE;
|
||||
|
||||
if (m_lastMsgNumber > 0)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
if (newstatus) *newstatus=0;
|
||||
return NS_OK;
|
||||
// nsNNTPNewsgroupList object gets deleted by the master when a new one is created.
|
||||
}
|
||||
|
||||
|
||||
nsresult nsNNTPNewsgroupListStub::ClearXOVERState()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
extern "C" nsresult NS_NewNewsgroupList(nsINNTPNewsgroupList **aInstancePtrResult,
|
||||
nsINNTPHost *newsHost,
|
||||
nsINNTPNewsgroup *newsgroup)
|
||||
{
|
||||
nsNNTPNewsgroupListStub * stub = nsnull;
|
||||
stub = new nsNNTPNewsgroupListStub(newsHost, newsgroup);
|
||||
nsresult rv = stub->QueryInterface(kINNTPNewsgroupListIID, (void **) aInstancePtrResult);
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,337 @@
|
|||
/* -*- 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.
|
||||
*/
|
||||
|
||||
/* This is a stub event sink for a NNTP Newsgroup introduced by mscott to test
|
||||
the NNTP protocol */
|
||||
|
||||
#include "nscore.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsISupports.h" /* interface nsISupports */
|
||||
|
||||
#include "nsINNTPNewsgroup.h"
|
||||
#include "nsNNTPArticleSet.h"
|
||||
|
||||
static NS_DEFINE_IID(kINNTPNewsgroupIID, NS_INNTPNEWSGROUP_IID);
|
||||
|
||||
class nsNNTPNewsgroupStub : public nsINNTPNewsgroup
|
||||
{
|
||||
|
||||
public:
|
||||
nsNNTPNewsgroupStub();
|
||||
virtual ~nsNNTPNewsgroupStub();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD GetName(char * *aName) const;
|
||||
NS_IMETHOD SetName(char * aName);
|
||||
|
||||
NS_IMETHOD GetPrettyName(char * *aPrettyName) const;
|
||||
NS_IMETHOD SetPrettyName(char * aPrettyName);
|
||||
|
||||
NS_IMETHOD GetPassword(char * *aPassword) const;
|
||||
NS_IMETHOD SetPassword(char * aPassword);
|
||||
|
||||
NS_IMETHOD GetUsername(char * *aUsername) const;
|
||||
NS_IMETHOD SetUsername(char * aUsername);
|
||||
|
||||
NS_IMETHOD GetNeedsExtraInfo(PRBool *aNeedsExtraInfo) const;
|
||||
NS_IMETHOD SetNeedsExtraInfo(PRBool aNeedsExtraInfo);
|
||||
|
||||
NS_IMETHOD IsOfflineArticle(PRInt32 num, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD GetCategory(PRBool *aCategory) const;
|
||||
NS_IMETHOD SetCategory(PRBool aCategory);
|
||||
|
||||
NS_IMETHOD GetSubscribed(PRBool *aSubscribed) const;
|
||||
NS_IMETHOD SetSubscribed(PRBool aSubscribed);
|
||||
|
||||
NS_IMETHOD GetWantNewTotals(PRBool *aWantNewTotals) const;
|
||||
NS_IMETHOD SetWantNewTotals(PRBool aWantNewTotals);
|
||||
|
||||
NS_IMETHOD GetNewsgroupList(nsINNTPNewsgroupList * *aNewsgroupList) const;
|
||||
NS_IMETHOD SetNewsgroupList(nsINNTPNewsgroupList * aNewsgroupList);
|
||||
|
||||
NS_IMETHOD UpdateSummaryFromNNTPInfo(PRInt32 oldest, PRInt32 youngest, PRInt32 total_messages);
|
||||
|
||||
protected:
|
||||
char * m_groupName;
|
||||
char * m_prettyName;
|
||||
char * m_password;
|
||||
char * m_userName;
|
||||
|
||||
PRBool m_isSubscribed;
|
||||
PRBool m_wantsNewTotals;
|
||||
PRBool m_needsExtraInfo;
|
||||
PRBool m_category;
|
||||
|
||||
nsINNTPNewsgroupList * m_newsgroupList;
|
||||
};
|
||||
|
||||
nsNNTPNewsgroupStub::nsNNTPNewsgroupStub()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_groupName = nsnull;
|
||||
m_prettyName = nsnull;
|
||||
m_password = nsnull;
|
||||
m_userName = nsnull;
|
||||
m_newsgroupList = nsnull;
|
||||
m_needsExtraInfo = PR_FALSE;
|
||||
m_category = PR_FALSE;
|
||||
}
|
||||
|
||||
nsNNTPNewsgroupStub::~nsNNTPNewsgroupStub()
|
||||
{
|
||||
printf("destroying newsgroup: %s", m_groupName ? m_groupName : "");
|
||||
NS_IF_RELEASE(m_newsgroupList);
|
||||
PR_FREEIF(m_groupName);
|
||||
PR_FREEIF(m_password);
|
||||
PR_FREEIF(m_userName);
|
||||
PR_FREEIF(m_prettyName);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNNTPNewsgroupStub, kINNTPNewsgroupIID);
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetName(char ** aName) const
|
||||
{
|
||||
if (aName)
|
||||
{
|
||||
*aName = PL_strdup(m_groupName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetName(char *aName)
|
||||
{
|
||||
if (aName)
|
||||
{
|
||||
printf("Setting newsgroup name to %s. \n", aName);
|
||||
m_groupName = PL_strdup(aName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetPrettyName(char ** aName) const
|
||||
{
|
||||
if (aName)
|
||||
{
|
||||
*aName = PL_strdup(m_prettyName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetPrettyName(char *aName)
|
||||
{
|
||||
if (aName)
|
||||
{
|
||||
printf("Setting pretty newsgroup name to %s. \n", aName);
|
||||
m_prettyName = PL_strdup(aName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetPassword(char ** aName) const
|
||||
{
|
||||
if (aName)
|
||||
{
|
||||
*aName = PL_strdup(m_password);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetPassword(char *aName)
|
||||
{
|
||||
if (aName)
|
||||
{
|
||||
printf("Setting password for newsgroup %s to %s. \n", m_groupName, aName);
|
||||
m_password = PL_strdup(aName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetUsername(char ** aUsername) const
|
||||
{
|
||||
if (aUsername)
|
||||
{
|
||||
*aUsername = PL_strdup(m_userName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetUsername(char *aUsername)
|
||||
{
|
||||
if (aUsername)
|
||||
{
|
||||
printf("Setting username for newsgroup %s to %s. \n", m_groupName, aUsername);
|
||||
m_userName = PL_strdup(aUsername);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetNeedsExtraInfo(PRBool *aNeedsExtraInfo) const
|
||||
{
|
||||
if (aNeedsExtraInfo)
|
||||
{
|
||||
*aNeedsExtraInfo = m_needsExtraInfo;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetNeedsExtraInfo(PRBool aNeedsExtraInfo)
|
||||
{
|
||||
if (aNeedsExtraInfo)
|
||||
{
|
||||
printf("Setting needs extra info for newsgroup %s to %s. \n", m_groupName, aNeedsExtraInfo ? "TRUE" : "FALSE" );
|
||||
m_needsExtraInfo = aNeedsExtraInfo;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::IsOfflineArticle(PRInt32 num, PRBool *_retval)
|
||||
{
|
||||
printf("Testing for offline article %d in %s. \n", num, m_groupName);
|
||||
if (_retval)
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetCategory(PRBool *aCategory) const
|
||||
{
|
||||
if (aCategory)
|
||||
{
|
||||
*aCategory = m_category;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetCategory(PRBool aCategory)
|
||||
{
|
||||
if (aCategory)
|
||||
{
|
||||
printf("Setting is category for newsgroup %s to %s. \n", m_groupName, aCategory ? "TRUE" : "FALSE" );
|
||||
m_category = aCategory;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetSubscribed(PRBool *aSubscribed) const
|
||||
{
|
||||
if (aSubscribed)
|
||||
{
|
||||
*aSubscribed = m_isSubscribed;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetSubscribed(PRBool aSubscribed)
|
||||
{
|
||||
if (aSubscribed)
|
||||
{
|
||||
printf("Setting is subscribed for newsgroup %s to %s. \n", m_groupName, aSubscribed ? "TRUE" : "FALSE" );
|
||||
m_isSubscribed = aSubscribed;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetWantNewTotals(PRBool *aWantNewTotals) const
|
||||
{
|
||||
if (aWantNewTotals)
|
||||
{
|
||||
*aWantNewTotals = m_wantsNewTotals;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetWantNewTotals(PRBool aWantNewTotals)
|
||||
{
|
||||
if (aWantNewTotals)
|
||||
{
|
||||
printf("Setting wants new totals for newsgroup %s to %s. \n", m_groupName, aWantNewTotals ? "TRUE" : "FALSE" );
|
||||
m_wantsNewTotals = aWantNewTotals;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::GetNewsgroupList(nsINNTPNewsgroupList * *aNewsgroupList) const
|
||||
{
|
||||
if (aNewsgroupList)
|
||||
{
|
||||
*aNewsgroupList = m_newsgroupList;
|
||||
NS_IF_ADDREF(m_newsgroupList);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::SetNewsgroupList(nsINNTPNewsgroupList * aNewsgroupList)
|
||||
{
|
||||
if (aNewsgroupList)
|
||||
{
|
||||
printf("Setting newsgroup list for newsgroup %s. \n", m_groupName);
|
||||
m_newsgroupList = aNewsgroupList;
|
||||
NS_IF_ADDREF(m_newsgroupList);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNNTPNewsgroupStub::UpdateSummaryFromNNTPInfo(PRInt32 oldest, PRInt32 youngest, PRInt32 total_messages)
|
||||
{
|
||||
printf("Updating summary with oldest= %d, youngest= %d, and total messages = %d. \n", oldest, youngest, total_messages);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
nsresult NS_NewNewsgroup(nsINNTPNewsgroup **info,
|
||||
char *line,
|
||||
nsNNTPArticleSet *set,
|
||||
PRBool subscribed,
|
||||
nsINNTPHost *host,
|
||||
int depth)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsNNTPNewsgroupStub * group = new nsNNTPNewsgroupStub();
|
||||
if (group)
|
||||
{
|
||||
group->SetSubscribed(subscribed);
|
||||
rv = group->QueryInterface(kINNTPNewsgroupIID, (void **) info);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче