From d16e31e6e7dc17d07ea85e10c16a3e92d34067fb Mon Sep 17 00:00:00 2001 From: "sspitzer%netscape.com" Date: Tue, 4 May 1999 02:35:32 +0000 Subject: [PATCH] changes to get nntpTest (and eventually news) working --- mailnews/news/src/makefile.win | 4 + mailnews/news/src/nsNNTPArticleList.cpp | 2 +- mailnews/news/src/nsNNTPCategoryContainer.cpp | 101 ++ mailnews/news/src/nsNNTPHost.cpp | 999 +++++++++++++----- mailnews/news/src/nsNNTPHost.h | 8 +- mailnews/news/src/nsNNTPNewsgroup.cpp | 341 ++++++ mailnews/news/src/nsNNTPNewsgroup.h | 1 + mailnews/news/src/nsNNTPNewsgroupList.cpp | 103 +- mailnews/news/src/nsNNTPNewsgroupList.h | 4 +- mailnews/news/src/nsNNTPNewsgroupPost.cpp | 2 + mailnews/news/src/nsNNTPProtocol.cpp | 118 ++- mailnews/news/src/nsNntpService.cpp | 92 +- mailnews/news/src/nsNntpService.h | 2 + mailnews/news/src/nsNntpUrl.cpp | 5 + 14 files changed, 1424 insertions(+), 358 deletions(-) create mode 100644 mailnews/news/src/nsNNTPCategoryContainer.cpp create mode 100644 mailnews/news/src/nsNNTPNewsgroup.cpp diff --git a/mailnews/news/src/makefile.win b/mailnews/news/src/makefile.win index 828aac6345f..e83fc9226f2 100644 --- a/mailnews/news/src/makefile.win +++ b/mailnews/news/src/makefile.win @@ -31,6 +31,8 @@ CPPSRCS= nsNNTPProtocol.cpp \ nsNNTPArticleList.cpp \ nsNNTPNewsgroupList.cpp \ nsNNTPNewsgroupPost.cpp \ + nsNNTPNewsgroup.cpp \ + nsNNTPCategoryContainer.cpp \ nsNNTPHost.cpp \ nsNntpService.cpp \ nsNewsFolder.cpp \ @@ -46,6 +48,8 @@ CPP_OBJS= .\$(OBJDIR)\nsNNTPProtocol.obj \ .\$(OBJDIR)\nsNNTPNewsgroupList.obj \ .\$(OBJDIR)\nsNNTPNewsgroupPost.obj \ .\$(OBJDIR)\nsNNTPHost.obj \ + .\$(OBJDIR)\nsNNTPNewsgroup.obj \ + .\$(OBJDIR)\nsNNTPCategoryContainer.obj \ .\$(OBJDIR)\nsNntpService.obj \ .\$(OBJDIR)\nsNewsFolder.obj \ .\$(OBJDIR)\nsNntpIncomingServer.obj \ diff --git a/mailnews/news/src/nsNNTPArticleList.cpp b/mailnews/news/src/nsNNTPArticleList.cpp index acaaf4ab37f..b83d8f42e25 100644 --- a/mailnews/news/src/nsNNTPArticleList.cpp +++ b/mailnews/news/src/nsNNTPArticleList.cpp @@ -118,7 +118,7 @@ nsNNTPArticleList::~nsNNTPArticleList() nsresult nsNNTPArticleList::AddArticleKey(PRInt32 key) { -#ifdef DEBUG_mscott +#if defined(DEBUG_mscott) || defined(DEBUG_sspitzer) char * groupname = nsnull; if (m_newsgroup) m_newsgroup->GetName(&groupname); diff --git a/mailnews/news/src/nsNNTPCategoryContainer.cpp b/mailnews/news/src/nsNNTPCategoryContainer.cpp new file mode 100644 index 00000000000..204cbe341ce --- /dev/null +++ b/mailnews/news/src/nsNNTPCategoryContainer.cpp @@ -0,0 +1,101 @@ +/* -*- 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 + +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, nsINNTPCategoryContainer::GetIID()); + +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(nsINNTPCategoryContainer::GetIID(), (void **) aInstancePtr); + } + + return rv; +} + +} diff --git a/mailnews/news/src/nsNNTPHost.cpp b/mailnews/news/src/nsNNTPHost.cpp index 41bbc825a1d..1a237b7e635 100644 --- a/mailnews/news/src/nsNNTPHost.cpp +++ b/mailnews/news/src/nsNNTPHost.cpp @@ -35,10 +35,17 @@ #include "nsINNTPNewsgroup.h" #include "nsNNTPNewsgroup.h" +#include "nsINNTPNewsgroupList.h" +#include "nsNNTPNewsgroupList.h" + #include "nsIMsgFolder.h" #include "nsISupportsArray.h" #include "nsIEnumerator.h" +#include "nsFileStream.h" + +#include "nsNewsUtils.h" + #include "prprf.h" #include "prmem.h" #include "plstr.h" @@ -56,16 +63,6 @@ static const char LINEBREAK_START = '\015'; #define PROTOCOL_DEBUG -/* externally declare this function...it doesn't exist in mailnews yet though...hmmm */ - -extern int msg_LineBuffer (const char *net_buffer, PRInt32 net_buffer_size, - char **bufferP, PRUint32 *buffer_sizeP, - PRUint32 *buffer_fpP, - PRBool convert_newlines_p, - PRInt32 (*per_line_fn) (char *line, PRUint32 line_length, void *closure), - void *closure); - - class nsNNTPHost : public nsINNTPHost { public: #ifdef HAVE_MASTER @@ -84,48 +81,47 @@ public: m_supportsExtensions); NS_IMETHOD AddExtension (const char *ext); - NS_IMETHOD QueryExtension (const char *ext, PRBool *_retval); + NS_IMETHOD QueryExtension (const char *ext, PRBool *retval); NS_IMPL_CLASS_GETSET(PostingAllowed, PRBool, m_postingAllowed); NS_IMPL_CLASS_GETTER(GetPushAuth, PRBool, m_pushAuth); NS_IMETHOD SetPushAuth(PRBool value); - NS_IMPL_CLASS_GETSET(LastUpdatedTime, PRInt64, m_lastGroupUpdate); - - NS_IMETHOD GetNewsgroupList(const char *groupname, - nsINNTPNewsgroupList **_retval) { NS_ASSERTION(0, "unimplemented"); return NS_OK;}; + NS_IMPL_CLASS_GETSET(LastUpdatedTime, PRTime, m_lastGroupUpdate); + NS_IMETHOD GetNewsgroupList(const char *name,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) { NS_ASSERTION(0, "unimplemented!"); return NS_OK;} + NS_IMETHOD FindNewsgroup(const char *name, PRBool create, + nsINNTPNewsgroup **retval) { NS_ASSERTION(0, "unimplemented!"); return NS_OK;} NS_IMETHOD AddPropertyForGet (const char *property, const char *value); - NS_IMETHOD QueryPropertyForGet (const char *property, char **_retval); + NS_IMETHOD QueryPropertyForGet (const char *property, char **retval); - NS_IMETHOD AddSearchableGroup(const char *groupname); + NS_IMETHOD AddSearchableGroup(const char *name); // 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 SetIsVirtualGroup(const char *groupname, PRBool isVirtual, + NS_IMETHOD SetIsVirtualGroup(const char *name, PRBool isVirtual); + NS_IMETHOD SetIsVirtualGroup(const char *name, PRBool isVirtual, nsMsgGroupRecord *inGroupRecord); - NS_IMETHOD GetIsVirtualGroup(const char *groupname, PRBool *_retval); + NS_IMETHOD GetIsVirtualGroup(const char *name, PRBool *retval); // custom/searchable headers NS_IMETHOD AddSearchableHeader(const char *headerName); - NS_IMETHOD QuerySearchableHeader(const char *headerName, PRBool *_retval); + 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(); + NS_IMETHOD LoadNewsrc(const char *uri); // Write out the newsrc for this host right now. In general, either // MarkDirty() or WriteIfDirty() should be called instead. @@ -148,18 +144,18 @@ public: // (this is what the pre-mozilla API looked like) char *GetNewsrcFileName() { return m_filename; }; - NS_IMETHOD FindGroup(const char* name, nsINNTPNewsgroup* *_retval); - NS_IMETHOD AddGroup(const char *groupname, + NS_IMETHOD FindGroup(const char* name, nsINNTPNewsgroup* *retval); + NS_IMETHOD AddGroup(const char *name, nsINNTPNewsgroup **retval); - NS_IMETHOD AddGroup(const char *groupname, + NS_IMETHOD AddGroup(const char *name, nsMsgGroupRecord *groupRecord, nsINNTPNewsgroup **retval); - NS_IMETHOD RemoveGroupByName(const char *groupName); + NS_IMETHOD RemoveGroupByName(const char *name); NS_IMETHOD RemoveGroup(nsINNTPNewsgroup*); - NS_IMETHOD AddNewNewsgroup(const char *groupName, + NS_IMETHOD AddNewNewsgroup(const char *name, PRInt32 first, PRInt32 last, const char *flags, @@ -167,7 +163,7 @@ public: /* Name of directory to store newsgroup databases in. This needs to have - "/groupname" appended to it, and the + "/name" 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) {NS_ASSERTION(0, "unimplemented"); return NS_OK;}; @@ -177,9 +173,9 @@ public: /* 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) { return NS_OK;} + NS_IMETHOD GetGroupList(char **retval) { return NS_OK;} - NS_IMETHOD DisplaySubscribedGroup(const char *groupname, + NS_IMETHOD DisplaySubscribedGroup(const char *name, PRInt32 first_message, PRInt32 last_message, PRInt32 total_messages, @@ -187,6 +183,9 @@ public: // end of nsINNTPHost private: + nsresult LoadNewsrcFileAndCreateNewsgroups(nsFileSpec &newsrcFile); + nsresult MapHostToNewsrcFile(char *newshostname, nsFileSpec &fatFile, nsFileSpec &newsrcFile); + nsresult GetNewsrcFile(char *newshostname, nsFileSpec &path, nsFileSpec &newsrcFile); // simplify the QueryInterface calls static nsIMsgFolder *getFolderFor(nsINNTPNewsgroup *group); @@ -273,50 +272,50 @@ private: // Returns the pretty name for the given group. The resulting string // must be free'd using delete[]. - char* GetPrettyName(char* groupname); - NS_IMETHOD SetPrettyName(const char* groupname, const char* prettyname); + char* GetPrettyName(char* name); + NS_IMETHOD SetPrettyName(const char* name, const char* prettyname); - time_t GetAddTime(char* groupname); + PRTime GetAddTime(char* name); // Returns a unique integer associated with this newsgroup. This is // mostly used by Win16 to generate a 8.3 filename. - PRInt32 GetUniqueID(char* groupname); + PRInt32 GetUniqueID(char* name); - PRBool IsCategory(char* groupname); - PRBool IsCategoryContainer(char* groupname); - int SetIsCategoryContainer(const char* groupname, PRBool value, nsMsgGroupRecord *inGroupRecord = NULL); + PRBool IsCategory(char* name); + PRBool IsCategoryContainer(char* name); + int SetIsCategoryContainer(const char* name, PRBool value, nsMsgGroupRecord *inGroupRecord = NULL); - NS_IMETHOD SetGroupNeedsExtraInfo(const char *groupname, PRBool value); + NS_IMETHOD SetGroupNeedsExtraInfo(const char *name, 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); + char* GetCategoryContainer(const char* name, nsMsgGroupRecord *inGroupRecord = NULL); + nsINNTPNewsgroup *GetCategoryContainerFolderInfo(const char *name); // Get/Set whether this is a real group (as opposed to a container of // other groups, like "mcom".) - PRBool IsGroup(char* groupname); - int SetIsGroup(char* groupname, PRBool value); + PRBool IsGroup(char* name); + int SetIsGroup(char* name, PRBool value); // Returns PR_TRUE if it's OK to post HTML in this group (either because the // bit is on for this group, or one of this group's ancestor's has marked // all of its descendents as being OK for HTML.) - PRBool IsHTMLOk(char* groupname); + PRBool IsHTMLOk(char* name); // Get/Set if it's OK to post HTML in just this group. - PRBool IsHTMLOKGroup(char* groupname); - int SetIsHTMLOKGroup(char* groupname, PRBool value); + PRBool IsHTMLOKGroup(char* name); + int SetIsHTMLOKGroup(char* name, PRBool value); // Get/Set if it's OK to post HTML in this group and all of its subgroups. - PRBool IsHTMLOKTree(char* groupname); - int SetIsHTMLOKTree(char* groupname, PRBool value); + PRBool IsHTMLOKTree(char* name); + int SetIsHTMLOKTree(char* name, PRBool value); // Create the given group (if not already present). Returns 0 if the // group is already present, 1 if we had to create it, negative on error. // The given group will have the "isgroup" bit set on it (in other words, // it is not to be just a container of other groups, like "mcom" is.) - int NoticeNewGroup(const char* groupname, nsMsgGroupRecord **outGroupRecord = NULL); + int NoticeNewGroup(const char* name, nsMsgGroupRecord **outGroupRecord = NULL); // Makes sure that we have records in memory for all known descendants @@ -339,28 +338,28 @@ private: int EmptyInhale(); nsMsgGroupRecord* GetGroupTree() {return m_groupTree;} - time_t GetFirstNewDate() {return m_firstnewdate;} + PRTime GetFirstNewDate() {return m_firstnewdate;} - NS_IMETHOD GroupNotFound(const char *groupName, PRBool opening); + NS_IMETHOD GroupNotFound(const char *name, PRBool opening); int ReorderGroup (nsINNTPNewsgroup *groupToMove, nsINNTPNewsgroup *groupToMoveBefore, PRInt32 *newIdx); protected: void OpenGroupFile(const PRIntn = PR_WRONLY); - PRInt32 RememberLine(char* line); - static PRInt32 ProcessLine_s(char* line, PRUint32 line_size, void* closure); - PRInt32 ProcessLine(char* line, PRUint32 line_size); + nsresult RememberLine(char* line); + static nsresult ProcessLine_s(char* line, PRUint32 line_size, void* closure); + nsresult ProcessLine(char* line, PRUint32 line_size); static void WriteTimer(void* closure); int CreateFileHeader(); int ReadInitialPart(); nsMsgGroupRecord* FindGroupInBlock(nsMsgGroupRecord* parent, - char* groupname, + char* name, PRInt32* comp); nsMsgGroupRecord* LoadSingleEntry(nsMsgGroupRecord* parent, - char* groupname, + char* name, PRInt32 min, PRInt32 max); static PRInt32 InhaleLine(char* line, PRUint32 length, void* closure); - nsMsgGroupRecord* FindOrCreateGroup(const char* groupname, + nsMsgGroupRecord* FindOrCreateGroup(const char* name, int* statusOfMakingGroup = NULL); nsINNTPCategoryContainer *SwitchNewsToCategoryContainer(nsINNTPNewsgroup *newsInfo); @@ -373,6 +372,8 @@ protected: char* m_fullUIName; nsISupportsArray* m_groups; // List of nsINNTPNewsgroup* objects. + nsISupportsArray* m_newsgrouplists; // List of nsINNTPNewsgroupList* objects. + #ifdef HAVE_MASTER MSG_Master* m_master; #endif @@ -430,8 +431,8 @@ protected: PRBool m_pushAuth; // PR_TRUE if we should volunteer authentication without a // challenge - time_t m_lastGroupUpdate; - time_t m_firstnewdate; + PRTime m_lastGroupUpdate; + PRTime m_firstnewdate; nsMsgGroupRecord* m_groupTree; // Tree of groups we're remembering. @@ -492,6 +493,7 @@ nsNNTPHost::nsNNTPHost(const char *name, PRInt32 port) m_optionLines = NULL; m_filename = NULL; m_groups = NULL; + m_newsgrouplists = NULL; m_dbfilename = NULL; m_dirty = 0; m_writetimer = NULL; @@ -519,6 +521,7 @@ nsNNTPHost::CleanUp() { PR_FREEIF(m_nameAndPort); PR_FREEIF(m_fullUIName); NS_IF_RELEASE(m_groups); + NS_IF_RELEASE(m_newsgrouplists); delete [] m_dbfilename; delete m_groupTree; if (m_block) @@ -587,7 +590,7 @@ nsNNTPHost::OpenGroupFile(const PRIntn permissions) void nsNNTPHost::ClearNew() { - m_firstnewdate = time(0) + 1; + m_firstnewdate = PR_Now() + 1; } @@ -605,7 +608,7 @@ PRInt32 nsNNTPHost::getPort() #if 0 NS_IMETHODIMP -nsNNTPHost::GetLastUpdatedTime(PRInt64* aLastUpdatedTime) +nsNNTPHost::GetLastUpdatedTime(PRTime* aLastUpdatedTime) { *aLastUpdatedTime = m_lastGroupUpdate; @@ -613,7 +616,7 @@ nsNNTPHost::GetLastUpdatedTime(PRInt64* aLastUpdatedTime) } NS_IMETHODIMP -nsNNTPHost::setLastUpdate(PRInt64 aLastUpdatedTime) +nsNNTPHost::setLastUpdate(PRTime aLastUpdatedTime) { m_lastGroupUpdate = aLastUpdatedTime; return NS_MSG_SUCCESS; @@ -639,41 +642,256 @@ const char* nsNNTPHost::getFullUIName() return m_fullUIName; } -PRInt32 -nsNNTPHost::RememberLine(char* line) +/* sspitzer: from mozilla/network/protocol/pop3/mkpop3.c */ + +static PRInt32 +msg_GrowBuffer (PRUint32 desired_size, PRUint32 element_size, PRUint32 quantum, + char **buffer, PRUint32 *size) { - char* new_data; - if (m_optionLines) { - new_data = - (char *) PR_REALLOC(m_optionLines, - PL_strlen(m_optionLines) - + PL_strlen(line) + 4); - } else { - new_data = (char *) PR_Malloc(PL_strlen(line) + 3); + if (*size <= desired_size) + { + char *new_buf; + PRUint32 increment = desired_size - *size; + if (increment < quantum) /* always grow by a minimum of N bytes */ + increment = quantum; + +#ifdef TESTFORWIN16 + if (((*size + increment) * (element_size / sizeof(char))) >= 64000) + { + /* Make sure we don't choke on WIN16 */ + PR_ASSERT(0); + return -1; + } +#endif /* DEBUG */ + + new_buf = (*buffer + ? (char *) PR_Realloc (*buffer, (*size + increment) + * (element_size / sizeof(char))) + : (char *) PR_Malloc ((*size + increment) + * (element_size / sizeof(char)))); + if (! new_buf) + return -1; // NS_ERROR_OUT_OF_MEMORY; + *buffer = new_buf; + *size += increment; } - if (!new_data) return MK_OUT_OF_MEMORY; - PL_strcpy(new_data, line); - PL_strcat(new_data, MSG_LINEBREAK); - - m_optionLines = new_data; - - return 0; - + return 0; } +/* Take the given buffer, tweak the newlines at the end if necessary, and + send it off to the given routine. We are guaranteed that the given + buffer has allocated space for at least one more character at the end. */ +static PRInt32 +msg_convert_and_send_buffer(char* buf, PRUint32 length, PRBool convert_newlines_p, + nsresult (*per_line_fn) (char *line, + PRUint32 line_length, + void *closure), + void *closure) +{ + /* Convert the line terminator to the native form. + */ + char* newline; -PRInt32 + PR_ASSERT(buf && length > 0); + if (!buf || length <= 0) return -1; + newline = buf + length; + PR_ASSERT(newline[-1] == CR || newline[-1] == LF); + if (newline[-1] != CR && newline[-1] != LF) return -1; + + if (!convert_newlines_p) + { + } +#if (LINEBREAK_LEN == 1) + else if ((newline - buf) >= 2 && + newline[-2] == CR && + newline[-1] == LF) + { + /* CRLF -> CR or LF */ + buf [length - 2] = LINEBREAK[0]; + length--; + } + else if (newline > buf + 1 && + newline[-1] != LINEBREAK[0]) + { + /* CR -> LF or LF -> CR */ + buf [length - 1] = LINEBREAK[0]; + } +#else + else if (((newline - buf) >= 2 && newline[-2] != CR) || + ((newline - buf) >= 1 && newline[-1] != LF)) + { + /* LF -> CRLF or CR -> CRLF */ + length++; + buf[length - 2] = LINEBREAK[0]; + buf[length - 1] = LINEBREAK[1]; + } +#endif + + return (*per_line_fn)(buf, length, closure); +} + +static PRInt32 +msg_LineBuffer (const char *net_buffer, PRInt32 net_buffer_size, + char **bufferP, PRUint32 *buffer_sizeP, PRUint32 *buffer_fpP, + PRBool convert_newlines_p, + nsresult (*per_line_fn) (char *line, PRUint32 line_length, + void *closure), + void *closure) +{ +#ifdef DEBUG_sspitzer_ + printf("msg_LineBuffer()\n"); +#endif + + PRInt32 status = 0; + if (*buffer_fpP > 0 && *bufferP && (*bufferP)[*buffer_fpP - 1] == CR && + net_buffer_size > 0 && net_buffer[0] != LF) { + /* The last buffer ended with a CR. The new buffer does not start + with a LF. This old buffer should be shipped out and discarded. */ + PR_ASSERT(*buffer_sizeP > *buffer_fpP); + if (*buffer_sizeP <= *buffer_fpP) return -1; + status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP, + convert_newlines_p, + per_line_fn, closure); + if (status < 0) return status; + *buffer_fpP = 0; + } + while (net_buffer_size > 0) + { + const char *net_buffer_end = net_buffer + net_buffer_size; + const char *newline = 0; + const char *s; + + + for (s = net_buffer; s < net_buffer_end; s++) + { + /* Move forward in the buffer until the first newline. + Stop when we see CRLF, CR, or LF, or the end of the buffer. + *But*, if we see a lone CR at the *very end* of the buffer, + treat this as if we had reached the end of the buffer without + seeing a line terminator. This is to catch the case of the + buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n". + */ + if (*s == CR || *s == LF) + { + newline = s; + if (newline[0] == CR) + { + if (s == net_buffer_end - 1) + { + /* CR at end - wait for the next character. */ + newline = 0; + break; + } + else if (newline[1] == LF) + /* CRLF seen; swallow both. */ + newline++; + } + newline++; + break; + } + } + + /* Ensure room in the net_buffer and append some or all of the current + chunk of data to it. */ + { + const char *end = (newline ? newline : net_buffer_end); + PRUint32 desired_size = (end - net_buffer) + (*buffer_fpP) + 1; + + if (desired_size >= (*buffer_sizeP)) + { + status = msg_GrowBuffer (desired_size, sizeof(char), 1024, + bufferP, buffer_sizeP); + if (status < 0) return status; + } + nsCRT::memcpy((*bufferP) + (*buffer_fpP), net_buffer, (end - net_buffer)); + (*buffer_fpP) += (end - net_buffer); + } + + /* Now *bufferP contains either a complete line, or as complete + a line as we have read so far. + + If we have a line, process it, and then remove it from `*bufferP'. + Then go around the loop again, until we drain the incoming data. + */ + if (!newline) + return 0; + + status = msg_convert_and_send_buffer(*bufferP, *buffer_fpP, + convert_newlines_p, + per_line_fn, closure); + if (status < 0) return status; + + net_buffer_size -= (newline - net_buffer); + net_buffer = newline; + (*buffer_fpP) = 0; + } + return 0; +} + +nsresult +nsNNTPHost::LoadNewsrcFileAndCreateNewsgroups(nsFileSpec &newsrcFile) +{ + char *ibuffer = 0; + PRUint32 ibuffer_size = 0; + PRUint32 ibuffer_fp = 0; + int size = 1024; + char *buffer; + buffer = new char[size]; + nsresult rv = NS_OK; + PRInt32 numread = 0; + PRInt32 status = 0; + + PR_FREEIF(m_optionLines); + + if (!buffer) return NS_ERROR_OUT_OF_MEMORY; + + nsInputFileStream inputStream(newsrcFile); + while (1) { + numread = inputStream.read(buffer, size); + if (numread == 0) { + break; + } + else { +#ifdef DEBUG_sspitzer_ + printf("%d: %s\n", numread, buffer); +#endif + status = msg_LineBuffer(buffer, numread, + &ibuffer, &ibuffer_size, &ibuffer_fp, + FALSE, +#ifdef XP_OS2 + (nsresult (_Optlink*) (char*,PRUint32,void*)) +#endif /* XP_OS2 */ + nsNNTPHost::ProcessLine_s, this); + if (numread <= 0) { + break; + } + } + } + + if (status == 0 && ibuffer_fp > 0) { + rv = ProcessLine_s(ibuffer, ibuffer_fp, this); + ibuffer_fp = 0; + } + + inputStream.close(); + delete [] buffer; + + return rv; +} + +nsresult nsNNTPHost::ProcessLine_s(char* line, PRUint32 line_size, void* closure) { - return ((nsNNTPHost*) closure)->ProcessLine(line, line_size); +#ifdef DEBUG_sspitzer_ + printf("nsNNTPHost::ProcessLine_s()\n"); +#endif + return ((nsNNTPHost*) closure)->ProcessLine(line, line_size); } - -PRInt32 +nsresult nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) { /* guard against blank line lossage */ - if (line[0] == '#' || line[0] == CR || line[0] == LF) return 0; + if (line[0] == '#' || line[0] == CR || line[0] == LF) return NS_OK; line[line_size] = 0; @@ -696,7 +914,7 @@ nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) } set = nsNNTPArticleSet::Create(s + 1, this); - if (!set) return MK_OUT_OF_MEMORY; + if (!set) return NS_ERROR_OUT_OF_MEMORY; PRBool subscribed = (*s == ':'); *s = '\0'; @@ -704,10 +922,10 @@ nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) if (PL_strlen(line) == 0) { delete set; - return 0; + return NS_OK; } - nsINNTPNewsgroup* info=NULL; + nsINNTPNewsgroup* info=nsnull; nsresult rv=NS_ERROR_NOT_INITIALIZED; if (subscribed && IsCategoryContainer(line)) @@ -736,7 +954,7 @@ nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) // autosubscribe, if we haven't seen this one. char* groupLine = PR_smprintf("%s:", fullname); if (groupLine) { - ProcessLine(groupLine, PL_strlen(groupLine)); + rv = ProcessLine(groupLine, PL_strlen(groupLine)); PR_Free(groupLine); } } else { @@ -746,17 +964,28 @@ nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) } } else { - PRUint32 depth; - rv = m_hostinfo->GetDepth(&depth); + PRUint32 depth = 1; + rv = NS_OK; + /* rv = m_hostinfo->GetDepth(&depth); */ -#if 0 // not defined yet - if (NS_SUCCEEDED(rv)) + if (NS_SUCCEEDED(rv)) { rv = NS_NewNewsgroup(&info, line, set, subscribed, this, depth+1); -#endif + + if (NS_SUCCEEDED(rv)) { + nsINNTPNewsgroupList *newsgroupList = nsnull; + + rv = NS_NewNewsgroupList(&newsgroupList, this, info, line, "foobar"); + if (NS_SUCCEEDED(rv) && (newsgroupList != nsnull)) { + //add newsgroupList to host's list of newsgroups + if (m_newsgrouplists != nsnull) + m_newsgrouplists->AppendElement(newsgroupList); + } + } + } } - if (NS_FAILED(rv) || !info) return MK_OUT_OF_MEMORY; + if (NS_FAILED(rv) || !info) return NS_ERROR_OUT_OF_MEMORY; // for now, you can't subscribe to category by itself. nsINNTPCategory *category; @@ -774,7 +1003,12 @@ nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) NS_RELEASE(category); } - m_groups->AppendElement(info); + if (m_groups != nsnull) { + m_groups->AppendElement(info); + } + else { + printf("m_groups is null.\n"); + } // prime the folder info from the folder cache while it's still around. // Except this might disable the update of new counts - check it out... @@ -782,66 +1016,229 @@ nsNNTPHost::ProcessLine(char* line, PRUint32 line_size) m_master->InitFolderFromCache (info); #endif - return 0; + return NS_OK; +} + +nsresult +nsNNTPHost::RememberLine(char* line) +{ + char* new_data; + if (m_optionLines) { + new_data = + (char *) PR_Realloc(m_optionLines, + PL_strlen(m_optionLines) + + PL_strlen(line) + 4); + } else { + new_data = (char *) PR_Malloc(PL_strlen(line) + 3); + } + if (!new_data) + return NS_ERROR_OUT_OF_MEMORY; + + PL_strcpy(new_data, line); + PL_strcat(new_data, LINEBREAK); + + m_optionLines = new_data; + + return NS_OK; } -nsresult nsNNTPHost::LoadNewsrc(/* nsIMsgFolder* hostinfo*/) +#ifdef USE_NEWSRC_MAP_FILE + +#define NEWSRC_MAP_FILE_COOKIE "netscape-newsrc-map-file" + +nsresult +nsNNTPHost::MapHostToNewsrcFile(char *newshostname, nsFileSpec &fatFile, nsFileSpec &newsrcFile) { - char *ibuffer = 0; - PRUint32 ibuffer_size = 0; - PRUint32 ibuffer_fp = 0; + char *lookingFor = nsnull; + char buffer[512]; + char psuedo_name[512]; + char filename[512]; + char is_newsgroup[512]; + PRBool rv; + +#ifdef DEBUG_sspitzer_ + printf("MapHostToNewsrcFile(%s,%s,%s,??)\n",newshostname,(const char *)fatFile, newshostname); +#endif + lookingFor = PR_smprintf("newsrc-%s",newshostname); + if (lookingFor == nsnull) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsInputFileStream inputStream(fatFile); + + if (inputStream.eof()) { + newsrcFile = ""; + inputStream.close(); + PR_FREEIF(lookingFor); + return NS_ERROR_FAILURE; + } + + /* we expect the first line to be NEWSRC_MAP_FILE_COOKIE */ + rv = inputStream.readline(buffer, sizeof(buffer)); +#ifdef DEBUG_sspitzer_ + printf("buffer = %s\n", buffer); +#endif + if ((!rv) || (PL_strncmp(buffer, NEWSRC_MAP_FILE_COOKIE, PL_strlen(NEWSRC_MAP_FILE_COOKIE)))) { + newsrcFile = ""; + inputStream.close(); + PR_FREEIF(lookingFor); + return NS_ERROR_FAILURE; + } + + while (!inputStream.eof()) { + char * p; + int i; + + rv = inputStream.readline(buffer, sizeof(buffer)); + if (!rv) { + newsrcFile = ""; + inputStream.close(); + PR_FREEIF(lookingFor); + return NS_ERROR_FAILURE; + } + +#ifdef DEBUG_sspitzer_ + printf("buffer = %s\n", buffer); +#endif + + /* + This used to be scanf() call which would incorrectly + parse long filenames with spaces in them. - JRE + */ + + filename[0] = '\0'; + is_newsgroup[0]='\0'; + + for (i = 0, p = buffer; *p && *p != '\t' && i < 500; p++, i++) + psuedo_name[i] = *p; + psuedo_name[i] = '\0'; + if (*p) + { + for (i = 0, p++; *p && *p != '\t' && i < 500; p++, i++) + filename[i] = *p; + filename[i]='\0'; + if (*p) + { + for (i = 0, p++; *p && *p != '\r' && i < 500; p++, i++) + is_newsgroup[i] = *p; + is_newsgroup[i]='\0'; + } + } + + if(!PL_strncmp(is_newsgroup, "TRUE", 4)) { +#ifdef DEBUG_sspitzer_ + printf("is_newsgroups_file = TRUE\n"); +#endif + } + else { +#ifdef DEBUG_sspitzer_ + printf("is_newsgroups_file = FALSE\n"); +#endif + } + +#ifdef DEBUG_sspitzer_ + printf("psuedo_name=%s,filename=%s\n", psuedo_name, filename); +#endif + if (!PL_strncmp(psuedo_name,lookingFor,PL_strlen(lookingFor))) { +#ifdef DEBUG_sspitzer_ + printf("found a match for %s\n",lookingFor); +#endif + newsrcFile = filename; + inputStream.close(); + PR_FREEIF(lookingFor); + return NS_OK; + } + } + + // failed to find a match in the map file + newsrcFile = ""; + inputStream.close(); + PR_FREEIF(lookingFor); + return NS_ERROR_FAILURE; +} +#endif /* USE_NEWSRC_MAP_FILE */ + +nsresult +nsNNTPHost::GetNewsrcFile(char *newshostname, nsFileSpec &path, nsFileSpec &newsrcFile) +{ + nsresult rv = NS_OK; + + if (newshostname == nsnull) { + return NS_ERROR_NULL_POINTER; + } + +#ifdef USE_NEWSRC_MAP_FILE + // the fat file lives in the same directory as + // the newsrc files + nsFileSpec fatFile(path); + fatFile.SetLeafName("fat"); + + rv = MapHostToNewsrcFile(newshostname, fatFile, newsrcFile); +#else + char *str = nsnull; + + str = PR_smprintf(".newsrc-%s", newshostname); + if (str == nsnull) { + return NS_ERROR_OUT_OF_MEMORY; + } + newsrcFile = path; + newsrcFile.SetLeafName(str); + PR_FREEIF(str); + str = nsnull; + rv = NS_OK; +#endif /* USE_NEWSRC_MAP_FILE */ + + return rv; +} + + +nsresult nsNNTPHost::LoadNewsrc(const char *uri/* , nsIMsgFolder* hostinfo*/) +{ + nsresult rv = NS_OK; /* m_hostinfo = hostinfo; PR_ASSERT(m_hostinfo); if (!m_hostinfo) return -1; */ -#ifdef UNREADY_CODE - int status = 0; - - PR_FREEIF(m_optionLines); - - if (!m_groups) { - int size = 2048; - char* buffer; - buffer = new char[size]; - if (!buffer) return MK_OUT_OF_MEMORY; - - m_groups = NS_NewISupportsArray(); - if (!m_groups) { - delete [] buffer; - return MK_OUT_OF_MEMORY; + if (!m_newsgrouplists) { + rv = NS_NewISupportsArray(&m_newsgrouplists); + if (NS_FAILED(rv) || (m_newsgrouplists == nsnull)) { + return NS_ERROR_OUT_OF_MEMORY; } - - XP_File fid = XP_FileOpen(GetNewsrcFileName(), - xpNewsRC, - XP_FILE_READ_BIN); - - if (fid) { - do { - status = XP_FileRead(buffer, size, fid); - if (status > 0) { - msg_LineBuffer(buffer, status, - &ibuffer, &ibuffer_size, &ibuffer_fp, - PR_FALSE, -#ifdef XP_OS2 - (PRInt32 (_Optlink*) (char*,PRUint32,void*)) -#endif - nsNNTPHost::ProcessLine_s, this); - } - } while (status > 0); - XP_FileClose(fid); - } - if (status == 0 && ibuffer_fp > 0) { - status = ProcessLine(ibuffer, ibuffer_fp); - ibuffer_fp = 0; - } - - delete [] buffer; - PR_FREEIF(ibuffer); - } + if (!m_groups) { + + rv = NS_NewISupportsArray(&m_groups); + if (NS_FAILED(rv) || (m_groups == nsnull)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsFileSpec newsrcFile(""); + nsFileSpec path(""); + + // turn uri into path + rv = nsNewsURI2Path(kNewsRootURI, uri, path); + if (NS_FAILED(rv)) { + return rv; + } + + rv = GetNewsrcFile(m_hostname, path, newsrcFile); + if (NS_FAILED(rv)) { + return rv; + } + +#ifdef DEBUG_sspitzer + printf("newsrc file = %s\n",(const char *)newsrcFile); +#endif + rv = LoadNewsrcFileAndCreateNewsgroups(newsrcFile); + if (NS_FAILED(rv)) { + return rv; + } + } + +#if 0 // build up the category tree for each category container so that roll-up // of counts will work before category containers are opened. for (PRInt32 i = 0; i < m_groups->Count(); i++) { @@ -854,11 +1251,11 @@ nsresult nsNNTPHost::LoadNewsrc(/* nsIMsgFolder* hostinfo*/) (void **)&catContainer); if (NS_SUCCEEDED(rv)) { - char* groupname; - nsresult rv = newsgroup->GetName(&groupname); + char* name; + nsresult rv = newsgroup->GetName(&name); nsMsgGroupRecord* group = - m_groupTree->FindDescendant(groupname); + m_groupTree->FindDescendant(name); PR_ASSERT(NS_SUCCEEDED(rv) && group); @@ -868,17 +1265,16 @@ nsresult nsNNTPHost::LoadNewsrc(/* nsIMsgFolder* hostinfo*/) MSG_FOLDER_FLAG_DIRECTORY); NS_RELEASE(folder); #ifdef HAVE_MASTER - catContainer->BuildCategoryTree(catContainer, groupname, group, + catContainer->BuildCategoryTree(catContainer, name, group, 2, m_master); #endif } NS_RELEASE(catContainer); } } +#endif /* 0 */ -#endif - - return 0; + return NS_OK; } @@ -948,14 +1344,14 @@ nsNNTPHost::WriteNewsrc() status = MK_OUT_OF_MEMORY; break; } - char *newsgroupName=NULL; + char *name=NULL; char *line; - rv = newsgroup->GetName(&newsgroupName); + rv = newsgroup->GetName(&name); PRBool isSubscribed=PR_FALSE; rv = newsgroup->GetSubscribed(&isSubscribed); line = PR_smprintf("%s%s %s" MSG_LINEBREAK, - newsgroupName, + name, isSubscribed ? ":" : "!", str); if (!line) { delete [] str; @@ -1038,11 +1434,11 @@ nsNNTPHost::SetNewsRCFilename(char* name) { delete [] m_filename; m_filename = new char [PL_strlen(name) + 1]; - if (!m_filename) return MK_OUT_OF_MEMORY; + if (!m_filename) return NS_ERROR_OUT_OF_MEMORY; PL_strcpy(m_filename, name); m_hostinfofilename = PR_smprintf("%s/hostinfo.dat", GetDBDirName()); - if (!m_hostinfofilename) return MK_OUT_OF_MEMORY; + if (!m_hostinfofilename) return NS_ERROR_OUT_OF_MEMORY; #ifdef UNREADY_CODE XP_StatStruct st; if (XP_Stat (m_hostinfofilename, &st, xpXoverCache) == 0) { @@ -1125,7 +1521,7 @@ nsNNTPHost::SetNewsRCFilename(char* name) return ReadInitialPart(); #else - return 0; + return NS_OK; #endif } @@ -1561,7 +1957,7 @@ nsNNTPHost::Inhale(PRBool force) &buffer, &buffer_size, &buffer_fp, PR_FALSE, #ifdef XP_OS2 - (PRInt32 (_Optlink*) (char*,PRUint32,void*)) + (nsresult (_Optlink*) (char*,PRUint32,void*)) #endif nsNNTPHost::InhaleLine, &state); } while (status >= 0); @@ -1609,18 +2005,28 @@ nsresult nsNNTPHost::FindGroup(const char* name, nsINNTPNewsgroup* *retval) { nsresult result = NS_ERROR_NOT_INITIALIZED; - + + if (name == nsnull) { + return NS_ERROR_NULL_POINTER; + } +#ifdef DEBUG_sspitzer + printf("FindGroup(%s)\n",name); +#endif + if (m_groups == NULL) return result; int n = m_groups->Count(); for (int i=0 ; iGetName(&newsgroupName); - - if (NS_SUCCEEDED(rv) && - PL_strcmp(newsgroupName, name) == 0) { + rv = info->GetName(&name); + +#ifdef DEBUG_sspitzer + printf("%d = %s\n",i,name?name:"null"); +#endif + + if (NS_SUCCEEDED(rv) && (name != nsnull) && PL_strcmp(name, name) == 0) { *retval = info; result = NS_OK; } @@ -1629,25 +2035,28 @@ nsNNTPHost::FindGroup(const char* name, nsINNTPNewsgroup* *retval) } nsresult -nsNNTPHost::AddGroup(const char *groupName, +nsNNTPHost::AddGroup(const char *name, nsINNTPNewsgroup **retval) { - return AddGroup(groupName, NULL, retval); + return AddGroup(name, NULL, retval); } nsresult -nsNNTPHost::AddGroup(const char *groupName, +nsNNTPHost::AddGroup(const char *name, nsMsgGroupRecord *inGroupRecord, nsINNTPNewsgroup **retval) { +#ifdef DEBUG_sspitzer + printf("nsNNTPHost::AddGroup(%s)\n",name); +#endif nsINNTPNewsgroup *newsInfo = NULL; nsINNTPCategoryContainer *categoryContainer = NULL; char* containerName = NULL; PRBool needpaneupdate = PR_FALSE; PRBool isSubscribed=FALSE; - nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(groupName); + nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(name); if (!group) goto DONE; // Out of memory. if (!group->IsCategoryContainer() && group->IsCategory()) { @@ -1669,8 +2078,8 @@ nsNNTPHost::AddGroup(const char *groupName, if (NS_FAILED(rv) || !isSubscribed) { - groupName = containerName; - group = FindOrCreateGroup(groupName); + name = containerName; + group = FindOrCreateGroup(name); } NS_RELEASE(newsInfo); // categoryContainer released at the end of this function @@ -1682,7 +2091,7 @@ nsNNTPHost::AddGroup(const char *groupName, needpaneupdate = m_hostinfo && !group->IsCategory(); nsresult rv; - rv = FindGroup(groupName, &newsInfo); + rv = FindGroup(name, &newsInfo); if (NS_SUCCEEDED(rv)) { // seems to be already added PRBool subscribed; rv = newsInfo->GetSubscribed(&subscribed); @@ -1702,22 +2111,27 @@ nsNNTPHost::AddGroup(const char *groupName, goto DONE; } } else { - char* groupLine = PR_smprintf("%s:", groupName); + char* groupLine = PR_smprintf("%s:", name); if (!groupLine) { goto DONE; // Out of memory. } // this will add and auto-subscribe - OK, a cheap hack. if (ProcessLine(groupLine, PL_strlen(groupLine)) == 0) { - // groups are added at end so look there first... - newsInfo = (nsINNTPNewsgroup *) - (*m_groups)[m_groups->Count() - 1]; - char *newsgroupName; - rv = newsInfo->GetName(&newsgroupName); + if (m_groups != nsnull) { + // groups are added at end so look there first... + newsInfo = (nsINNTPNewsgroup *) + (*m_groups)[m_groups->Count() - 1]; + } + + if (!newsInfo) goto DONE; + + char *name; + rv = newsInfo->GetName(&name); if (NS_SUCCEEDED(rv) && - PL_strcmp(newsgroupName, groupName)) { - rv = FindGroup(groupName, &newsInfo); + PL_strcmp(name, name)) { + rv = FindGroup(name, &newsInfo); PR_ASSERT(NS_SUCCEEDED(rv)); } } @@ -1778,7 +2192,7 @@ nsNNTPHost::AddGroup(const char *groupName, folder->SetFlag(MSG_FOLDER_FLAG_ELIDED); NS_IF_RELEASE(folder); #ifdef HAVE_MASTER - catContainer->BuildCategoryTree(catContainer, groupName, group, + catContainer->BuildCategoryTree(catContainer, name, group, ); #endif NS_RELEASE(catContainer); @@ -1787,7 +2201,7 @@ nsNNTPHost::AddGroup(const char *groupName, else if (group->IsCategory() && categoryContainer) { #ifdef HAVE_MASTER - categoryContainer->AddToCategoryTree(categoryContainer, groupName, group, m_master); + categoryContainer->AddToCategoryTree(categoryContainer, name, group, m_master); #endif } @@ -1916,11 +2330,11 @@ nsNNTPHost::RemoveGroup (nsINNTPNewsgroup *newsInfo) } nsresult -nsNNTPHost::RemoveGroupByName(const char* groupName) +nsNNTPHost::RemoveGroupByName(const char* name) { nsINNTPNewsgroup *newsInfo = NULL; - nsresult rv = FindGroup(groupName, &newsInfo); + nsresult rv = FindGroup(name, &newsInfo); if (NS_SUCCEEDED(rv)) RemoveGroup (newsInfo); @@ -2021,10 +2435,10 @@ nsNNTPHost::GetFirstGroupNeedingCounts(char **result) wantNewTotals && subscribed) { info->SetWantNewTotals(PR_FALSE); - char *newsgroupName; - nsresult rv = info->GetName(&newsgroupName); + char *name; + nsresult rv = info->GetName(&name); if (NS_SUCCEEDED(rv)) { - *result = PL_strdup(newsgroupName); + *result = PL_strdup(name); return NS_OK; } } @@ -2125,27 +2539,27 @@ nsNNTPHost::AddSearchableGroup (const char *group) } nsresult -nsNNTPHost::QuerySearchableGroup (const char *group, PRBool *_retval) +nsNNTPHost::QuerySearchableGroup (const char *group, PRBool *retval) { - *_retval = FALSE; + *retval = FALSE; for (int i = 0; i < m_searchableGroups.Count(); i++) { const char *searchableGroup = (const char*) m_searchableGroups[i]; char *starInSearchableGroup = NULL; if (!PL_strcmp(searchableGroup, "*")) { - *_retval = PR_TRUE; // everything is searchable + *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 + *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 + *retval = PR_TRUE; // this group is individually searchable return NS_OK; } } @@ -2322,9 +2736,9 @@ int nsNNTPHost::RemoveHost() char* -nsNNTPHost::GetPrettyName(char* groupname) +nsNNTPHost::GetPrettyName(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (group) { const char* orig = group->GetPrettyName(); if (orig) { @@ -2340,15 +2754,15 @@ nsNNTPHost::GetPrettyName(char* groupname) nsresult -nsNNTPHost::SetPrettyName(const char* groupname, const char* prettyname) +nsNNTPHost::SetPrettyName(const char* name, const char* prettyname) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return MK_OUT_OF_MEMORY; nsresult rv = group->SetPrettyName(prettyname); if (NS_FAILED(rv)) { nsINNTPNewsgroup *newsFolder; - rv = FindGroup(groupname, &newsFolder); + rv = FindGroup(name, &newsFolder); // make news folder forget prettyname so it will query again if (NS_SUCCEEDED(rv) && newsFolder) newsFolder->SetPrettyName(NULL); @@ -2362,53 +2776,53 @@ nsNNTPHost::SetPrettyName(const char* groupname, const char* prettyname) } -time_t -nsNNTPHost::GetAddTime(char* groupname) +PRTime +nsNNTPHost::GetAddTime(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return 0; return group->GetAddTime(); } PRInt32 -nsNNTPHost::GetUniqueID(char* groupname) +nsNNTPHost::GetUniqueID(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return 0; return group->GetUniqueID(); } PRBool -nsNNTPHost::IsCategory(char* groupname) +nsNNTPHost::IsCategory(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return PR_FALSE; return group->IsCategory(); } PRBool -nsNNTPHost::IsCategoryContainer(char* groupname) +nsNNTPHost::IsCategoryContainer(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return PR_FALSE; return group->IsCategoryContainer(); } int -nsNNTPHost::SetIsCategoryContainer(const char* groupname, PRBool value, nsMsgGroupRecord *inGroupRecord) +nsNNTPHost::SetIsCategoryContainer(const char* name, PRBool value, nsMsgGroupRecord *inGroupRecord) { nsresult rv; - nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(name); if (!group) return MK_OUT_OF_MEMORY; int status = group->SetIsCategoryContainer(value); m_groupTreeDirty |= status; if (status > 0) { nsINNTPNewsgroup *newsgroup; - rv = FindGroup(groupname, &newsgroup); + rv = FindGroup(name, &newsgroup); nsIMsgFolder *newsFolder = getFolderFor(newsgroup); @@ -2456,9 +2870,9 @@ nsNNTPHost::SetIsCategoryContainer(const char* groupname, PRBool value, nsMsgGro } nsresult -nsNNTPHost::SetGroupNeedsExtraInfo(const char *groupname, PRBool value) +nsNNTPHost::SetGroupNeedsExtraInfo(const char *name, PRBool value) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return MK_OUT_OF_MEMORY; nsresult rv = group->SetNeedsExtraInfo(value); if (NS_SUCCEEDED(rv)) m_groupTreeDirty |= 1; @@ -2467,9 +2881,9 @@ nsNNTPHost::SetGroupNeedsExtraInfo(const char *groupname, PRBool value) char* -nsNNTPHost::GetCategoryContainer(const char* groupname, nsMsgGroupRecord *inGroupRecord) +nsNNTPHost::GetCategoryContainer(const char* name, nsMsgGroupRecord *inGroupRecord) { - nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(name); if (group) { group = group->GetCategoryContainer(); if (group) return group->GetFullName(); @@ -2478,19 +2892,19 @@ nsNNTPHost::GetCategoryContainer(const char* groupname, nsMsgGroupRecord *inGrou } nsINNTPNewsgroup * -nsNNTPHost::GetCategoryContainerFolderInfo(const char *groupname) +nsNNTPHost::GetCategoryContainerFolderInfo(const char *name) { nsINNTPNewsgroup *newsgroup=NULL; nsresult rv; // because GetCategoryContainer returns NULL for a category container... - nsMsgGroupRecord *group = FindOrCreateGroup(groupname); + nsMsgGroupRecord *group = FindOrCreateGroup(name); if (group->IsCategoryContainer()) { - rv = FindGroup(groupname, &newsgroup); + rv = FindGroup(name, &newsgroup); if (NS_SUCCEEDED(rv)) return newsgroup; else return NULL; } - char *categoryContainerName = GetCategoryContainer(groupname); + char *categoryContainerName = GetCategoryContainer(name); if (categoryContainerName) { rv = FindGroup(categoryContainerName, &newsgroup); @@ -2501,9 +2915,9 @@ nsNNTPHost::GetCategoryContainerFolderInfo(const char *groupname) nsresult -nsNNTPHost::GetIsVirtualGroup(const char* groupname, PRBool *retval) +nsNNTPHost::GetIsVirtualGroup(const char* name, PRBool *retval) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) { *retval = PR_FALSE; return NS_OK; @@ -2514,15 +2928,15 @@ nsNNTPHost::GetIsVirtualGroup(const char* groupname, PRBool *retval) nsresult -nsNNTPHost::SetIsVirtualGroup(const char* groupname, PRBool value) +nsNNTPHost::SetIsVirtualGroup(const char* name, PRBool value) { - return SetIsVirtualGroup(groupname, value, nsnull); + return SetIsVirtualGroup(name, value, nsnull); } nsresult -nsNNTPHost::SetIsVirtualGroup(const char* groupname, PRBool value, +nsNNTPHost::SetIsVirtualGroup(const char* name, PRBool value, nsMsgGroupRecord* inGroupRecord) { - nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = (inGroupRecord) ? inGroupRecord : FindOrCreateGroup(name); if (!group) return NS_ERROR_OUT_OF_MEMORY; @@ -2534,18 +2948,18 @@ nsNNTPHost::SetIsVirtualGroup(const char* groupname, PRBool value, PRBool -nsNNTPHost::IsGroup(char* groupname) +nsNNTPHost::IsGroup(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return PR_FALSE; return group->IsGroup(); } int -nsNNTPHost::SetIsGroup(char* groupname, PRBool value) +nsNNTPHost::SetIsGroup(char* name, PRBool value) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return MK_OUT_OF_MEMORY; int status = group->SetIsGroup(value); m_groupTreeDirty |= status; @@ -2554,9 +2968,9 @@ nsNNTPHost::SetIsGroup(char* groupname, PRBool value) PRBool -nsNNTPHost::IsHTMLOk(char* groupname) +nsNNTPHost::IsHTMLOk(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return PR_FALSE; if (group->IsHTMLOKGroup()) return PR_TRUE; for ( ; group ; group = group->GetParent()) { @@ -2567,18 +2981,18 @@ nsNNTPHost::IsHTMLOk(char* groupname) PRBool -nsNNTPHost::IsHTMLOKGroup(char* groupname) +nsNNTPHost::IsHTMLOKGroup(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return PR_FALSE; return group->IsHTMLOKGroup(); } int -nsNNTPHost::SetIsHTMLOKGroup(char* groupname, PRBool value) +nsNNTPHost::SetIsHTMLOKGroup(char* name, PRBool value) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return MK_OUT_OF_MEMORY; int status = group->SetIsHTMLOKGroup(value); m_groupTreeDirty |= status; @@ -2587,18 +3001,18 @@ nsNNTPHost::SetIsHTMLOKGroup(char* groupname, PRBool value) PRBool -nsNNTPHost::IsHTMLOKTree(char* groupname) +nsNNTPHost::IsHTMLOKTree(char* name) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return PR_FALSE; return group->IsHTMLOKTree(); } int -nsNNTPHost::SetIsHTMLOKTree(char* groupname, PRBool value) +nsNNTPHost::SetIsHTMLOKTree(char* name, PRBool value) { - nsMsgGroupRecord* group = FindOrCreateGroup(groupname); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (!group) return MK_OUT_OF_MEMORY; int status = group->SetIsHTMLOKTree(value); m_groupTreeDirty |= status; @@ -2611,7 +3025,7 @@ nsNNTPHost::SetIsHTMLOKTree(char* groupname, PRBool value) nsMsgGroupRecord* nsNNTPHost::FindGroupInBlock(nsMsgGroupRecord* parent, - char* groupname, + char* name, PRInt32* comp) { #ifdef UNREADY_CODE @@ -2640,7 +3054,7 @@ RESTART: } while (*ptr == CR || *ptr == LF) ptr++; *ptr2 = '\0'; - PRInt32 c = nsMsgGroupRecord::GroupNameCompare(groupname, ptr); + PRInt32 c = nsMsgGroupRecord::nameCompare(name, ptr); *ptr2 = ','; if (c < 0) { if (*comp > 0) { @@ -2704,7 +3118,7 @@ RELOAD: nsMsgGroupRecord* -nsNNTPHost::LoadSingleEntry(nsMsgGroupRecord* parent, char* groupname, +nsNNTPHost::LoadSingleEntry(nsMsgGroupRecord* parent, char* name, PRInt32 min, PRInt32 max) { #ifdef UNREADY_CODE @@ -2715,7 +3129,7 @@ nsNNTPHost::LoadSingleEntry(nsMsgGroupRecord* parent, char* groupname, if (parent != m_groupTree) { char* pname = parent->GetFullName(); if (pname) { - PR_ASSERT(PL_strncmp(pname, groupname, PL_strlen(pname)) == 0); + PR_ASSERT(PL_strncmp(pname, name, PL_strlen(pname)) == 0); delete [] pname; pname = NULL; } @@ -2731,7 +3145,7 @@ nsNNTPHost::LoadSingleEntry(nsMsgGroupRecord* parent, char* groupname, // First, check if we happen to already have the line for this group in // memory. if (m_block[0]) { - result = FindGroupInBlock(parent, groupname, &comp); + result = FindGroupInBlock(parent, name, &comp); } while (!result && comp != 0 && min < max) { @@ -2742,7 +3156,7 @@ nsNNTPHost::LoadSingleEntry(nsMsgGroupRecord* parent, char* groupname, if (length < 0) length = 0; m_block[length] = '\0'; - result = FindGroupInBlock(parent, groupname, &comp); + result = FindGroupInBlock(parent, name, &comp); if (comp > 0) { min = mid + 1; @@ -2758,17 +3172,17 @@ nsNNTPHost::LoadSingleEntry(nsMsgGroupRecord* parent, char* groupname, nsMsgGroupRecord* -nsNNTPHost::FindOrCreateGroup(const char* groupname, +nsNNTPHost::FindOrCreateGroup(const char* name, int* statusOfMakingGroup) { char buf[256]; nsMsgGroupRecord* parent = m_groupTree; - const char* start = groupname; + const char* start = name; PR_ASSERT(start && *start); if (!start || !*start) return NULL; - PR_ASSERT(*start != '.'); // groupnames can't start with ".". + PR_ASSERT(*start != '.'); // names can't start with ".". if (*start == '.') return NULL; while (*start) @@ -2777,7 +3191,7 @@ nsNNTPHost::FindOrCreateGroup(const char* groupname, const char* end = PL_strchr(start, '.'); if (!end) end = start + PL_strlen(start); int length = end - start; - PR_ASSERT(length > 0); // groupnames can't contain ".." or end in + PR_ASSERT(length > 0); // names can't contain ".." or end in // a ".". if (length <= 0) return NULL; PR_ASSERT(length < sizeof(buf)); @@ -2808,10 +3222,10 @@ nsNNTPHost::FindOrCreateGroup(const char* groupname, { ptr = parent->GetSiblingOrAncestorSibling(); } - length = end - groupname; + length = end - name; char* tmp = new char[length + 1]; if (!tmp) return NULL; - PL_strncpyz(tmp, groupname, length + 1); + PL_strncpyz(tmp, name, length + 1); tmp[length] = '\0'; ptr = LoadSingleEntry(parent, tmp, prev->GetFileOffset(), @@ -2827,7 +3241,7 @@ nsNNTPHost::FindOrCreateGroup(const char* groupname, if (!ptr) { m_groupTreeDirty = 2; - ptr = nsMsgGroupRecord::Create(parent, buf, time(0), + ptr = nsMsgGroupRecord::Create(parent, buf, PR_Now(), m_uniqueId++, 0); if (!ptr) return NULL; } @@ -2843,10 +3257,10 @@ nsNNTPHost::FindOrCreateGroup(const char* groupname, int -nsNNTPHost::NoticeNewGroup(const char* groupname, nsMsgGroupRecord **outGroupRecord) +nsNNTPHost::NoticeNewGroup(const char* name, nsMsgGroupRecord **outGroupRecord) { int status = 0; - nsMsgGroupRecord* group = FindOrCreateGroup(groupname, &status); + nsMsgGroupRecord* group = FindOrCreateGroup(name, &status); if (!group) return MK_OUT_OF_MEMORY; if (outGroupRecord) *outGroupRecord = group; @@ -2884,7 +3298,7 @@ nsNNTPHost::AssureAllDescendentsLoaded(nsMsgGroupRecord* group) &buffer, &buffer_size, &buffer_fp, PR_FALSE, #ifdef XP_OS2 - (PRInt32 (_Optlink*) (char*,PRUint32,void*)) + (nsresult (_Optlink*) (char*,PRUint32,void*)) #endif nsNNTPHost::InhaleLine, &state); } while (status >= 0); @@ -2906,7 +3320,7 @@ nsNNTPHost::AssureAllDescendentsLoaded(nsMsgGroupRecord* group) } nsresult -nsNNTPHost::GroupNotFound(const char *groupName, PRBool opening) +nsNNTPHost::GroupNotFound(const char *name, PRBool opening) { // if no group command has succeeded, don't blow away categories. // The server might be wedged... @@ -2914,14 +3328,14 @@ nsNNTPHost::GroupNotFound(const char *groupName, PRBool opening) return NS_ERROR_NOT_INITIALIZED; nsresult rv; - nsMsgGroupRecord* group = FindOrCreateGroup(groupName); + nsMsgGroupRecord* group = FindOrCreateGroup(name); if (group && (group->IsCategory() || opening)) { nsINNTPNewsgroup *newsInfo = NULL; nsIMsgFolder *newsFolder = NULL; // get the group and corresponding folder - rv = FindGroup(groupName, &newsInfo); + rv = FindGroup(name, &newsInfo); if (NS_SUCCEEDED(rv)) newsFolder = getFolderFor(newsInfo); @@ -2929,7 +3343,7 @@ nsNNTPHost::GroupNotFound(const char *groupName, PRBool opening) m_groupTreeDirty |= 2; // deleting a group has to force a rewrite anyway if (group->IsCategory()) { - nsINNTPNewsgroup *catCont = GetCategoryContainerFolderInfo(groupName); + nsINNTPNewsgroup *catCont = GetCategoryContainerFolderInfo(name); if (catCont) { nsIMsgFolder *catFolder = getFolderFor(catCont); @@ -2945,13 +3359,11 @@ nsNNTPHost::GroupNotFound(const char *groupName, PRBool opening) } } } - else if (newsInfo) #ifdef HAVE_MASTER + else if (newsInfo) { m_master->BroadcastFolderDeleted (newsInfo); -#else - ; + } #endif - if (newsInfo) { m_hostinfo->RemoveElement(newsFolder); @@ -3070,6 +3482,39 @@ int nsNNTPHost::DeleteFiles () return 0; } +nsresult +nsNNTPHost::GetNewsgroupList(const char* name, nsINNTPNewsgroupList **retval) +{ + nsresult result = NS_ERROR_NOT_INITIALIZED; + + if (name == nsnull) { + return NS_ERROR_NULL_POINTER; + } +#ifdef DEBUG_sspitzer + printf("GetNewsgroupList(%s)\n",name); +#endif + + if (m_newsgrouplists == NULL) return result; + int n = m_newsgrouplists->Count(); + for (int i=0 ; iGetGroupName(&newsgroupname); + +#ifdef DEBUG_sspitzer + printf("%d = %s\n",i,newsgroupname?newsgroupname:"null"); +#endif + + if (NS_SUCCEEDED(rv) && (newsgroupname != nsnull) && PL_strcmp(name,newsgroupname) == 0) { + *retval = list; + result = NS_OK; + } + } + return result; +} + /* given a message id like asl93490@ahost.com, convert * it to a newsgroup and a message number within that group * (stolen from msgglue.cpp - MSG_NewsGroupAndNumberOfID) @@ -3094,7 +3539,7 @@ nsNNTPHost::GetNewsgroupAndNumberOfID(const char *message_id, { MSG_FolderInfoNews *newsFolderInfo = (MSG_FolderInfoNews *) folderInfo; - *groupName = newsFolderInfo->GetNewsgroupName(); + *name = newsFolderInfo->GetNewsgroupName(); } #endif return NS_OK; @@ -3103,7 +3548,7 @@ nsNNTPHost::GetNewsgroupAndNumberOfID(const char *message_id, /* this function originally lived in a pane */ nsresult -nsNNTPHost::AddNewNewsgroup(const char *groupName, +nsNNTPHost::AddNewNewsgroup(const char *name, PRInt32 first, PRInt32 last, const char *flags, @@ -3112,7 +3557,11 @@ nsNNTPHost::AddNewNewsgroup(const char *groupName, nsMsgGroupRecord *groupRecord = NULL; nsresult rv; - int status = NoticeNewGroup(groupName, &groupRecord); +#ifdef DEBUG_sspitzer + printf("nsNNTPHost::AddNewNewsgroup(%s,...)\n",name); +#endif + + int status = NoticeNewGroup(name, &groupRecord); if (status < 0) return status; /* this used to be for the pane */ @@ -3140,14 +3589,14 @@ nsNNTPHost::AddNewNewsgroup(const char *groupName, } if (xactiveFlags) { - SetIsCategoryContainer(groupName, bIsCategoryContainer, groupRecord); - SetIsVirtualGroup(groupName, bIsVirtual, groupRecord); + SetIsCategoryContainer(name, bIsCategoryContainer, groupRecord); + SetIsVirtualGroup(name, bIsVirtual, groupRecord); } if (status > 0) { // If this really is a new newsgroup, then if it's a category of a // subscribed newsgroup, then automatically subscribe to it. - char* containerName = GetCategoryContainer(groupName, groupRecord); + char* containerName = GetCategoryContainer(name, groupRecord); if (containerName) { nsINNTPNewsgroup* categoryInfo; rv = FindGroup(containerName, &categoryInfo); @@ -3158,7 +3607,7 @@ nsNNTPHost::AddNewNewsgroup(const char *groupName, if (isSubscribed) { // this autosubscribes categories of subscribed newsgroups. nsINNTPNewsgroup *newsgroup; - rv = AddGroup(groupName, groupRecord, &newsgroup); + rv = AddGroup(name, groupRecord, &newsgroup); if (NS_SUCCEEDED(rv)) NS_RELEASE(newsgroup); } @@ -3225,11 +3674,15 @@ MSG_IMPL_GETFOLDER(nsINNTPCategoryContainer) nsresult NS_NewNNTPHost(nsINNTPHost **aNNTPHost, const char* name, PRUint32 port) { - nsresult rv; nsNNTPHost *aHost = new nsNNTPHost(name, port); - if (aHost) + if (aHost) { return aHost->QueryInterface(nsINNTPHost::GetIID(), (void **)aNNTPHost); - return NS_ERROR_NOT_INITIALIZED; - + } + else { + return NS_ERROR_OUT_OF_MEMORY; + } } + + + diff --git a/mailnews/news/src/nsNNTPHost.h b/mailnews/news/src/nsNNTPHost.h index 4e0e6e1891b..1e6d547971e 100644 --- a/mailnews/news/src/nsNNTPHost.h +++ b/mailnews/news/src/nsNNTPHost.h @@ -21,9 +21,15 @@ #include "nsINNTPHost.h" +/* some platforms (like Windows and Mac) use a map file, because of + * file name length limitations. */ +#ifndef XP_UNIX +#define USE_NEWSRC_MAP_FILE +#endif + NS_BEGIN_EXTERN_C -nsresult NS_NewNNTPHost(nsINNTPHost **aInstancePtrResult, const char * name, PRUint32 port); +nsresult NS_NewNNTPHost(nsINNTPHost **aInstancePtrResult, const char *name, PRUint32 port); NS_END_EXTERN_C diff --git a/mailnews/news/src/nsNNTPNewsgroup.cpp b/mailnews/news/src/nsNNTPNewsgroup.cpp new file mode 100644 index 00000000000..6f99e66d2d6 --- /dev/null +++ b/mailnews/news/src/nsNNTPNewsgroup.cpp @@ -0,0 +1,341 @@ +/* -*- 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 "nscore.h" +#include "plstr.h" +#include "prmem.h" +#include + +#include "nsISupports.h" /* interface nsISupports */ + +#include "nsINNTPNewsgroup.h" +#include "nsNNTPArticleSet.h" + +class nsNNTPNewsgroup : public nsINNTPNewsgroup +{ + + public: + nsNNTPNewsgroup(); + virtual ~nsNNTPNewsgroup(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetName(char * *aName); + NS_IMETHOD SetName(char * aName); + + NS_IMETHOD GetPrettyName(char * *aPrettyName); + NS_IMETHOD SetPrettyName(char * aPrettyName); + + NS_IMETHOD GetPassword(char * *aPassword); + NS_IMETHOD SetPassword(char * aPassword); + + NS_IMETHOD GetUsername(char * *aUsername); + NS_IMETHOD SetUsername(char * aUsername); + + NS_IMETHOD GetNeedsExtraInfo(PRBool *aNeedsExtraInfo); + NS_IMETHOD SetNeedsExtraInfo(PRBool aNeedsExtraInfo); + + NS_IMETHOD IsOfflineArticle(PRInt32 num, PRBool *_retval); + + NS_IMETHOD GetCategory(PRBool *aCategory); + NS_IMETHOD SetCategory(PRBool aCategory); + + NS_IMETHOD GetSubscribed(PRBool *aSubscribed); + NS_IMETHOD SetSubscribed(PRBool aSubscribed); + + NS_IMETHOD GetWantNewTotals(PRBool *aWantNewTotals); + NS_IMETHOD SetWantNewTotals(PRBool aWantNewTotals); + + NS_IMETHOD GetNewsgroupList(nsINNTPNewsgroupList * *aNewsgroupList); + 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; +}; + +nsNNTPNewsgroup::nsNNTPNewsgroup() +{ + 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; +} + +nsNNTPNewsgroup::~nsNNTPNewsgroup() +{ + 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(nsNNTPNewsgroup, nsINNTPNewsgroup::GetIID()); + +nsresult nsNNTPNewsgroup::GetName(char ** aName) +{ + if (aName) + { + *aName = PL_strdup(m_groupName); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::SetName(char *aName) +{ + if (aName) + { + printf("Setting newsgroup name to %s. \n", aName); + m_groupName = PL_strdup(aName); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::GetPrettyName(char ** aName) +{ + if (aName) + { + *aName = PL_strdup(m_prettyName); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::SetPrettyName(char *aName) +{ + if (aName) + { + printf("Setting pretty newsgroup name to %s. \n", aName); + m_prettyName = PL_strdup(aName); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::GetPassword(char ** aName) +{ + if (aName) + { + *aName = PL_strdup(m_password); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::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 nsNNTPNewsgroup::GetUsername(char ** aUsername) +{ + if (aUsername) + { + *aUsername = PL_strdup(m_userName); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::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 nsNNTPNewsgroup::GetNeedsExtraInfo(PRBool *aNeedsExtraInfo) +{ + if (aNeedsExtraInfo) + { + *aNeedsExtraInfo = m_needsExtraInfo; + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::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 nsNNTPNewsgroup::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 nsNNTPNewsgroup::GetCategory(PRBool *aCategory) +{ + if (aCategory) + { + *aCategory = m_category; + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::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 nsNNTPNewsgroup::GetSubscribed(PRBool *aSubscribed) +{ + if (aSubscribed) + { + *aSubscribed = m_isSubscribed; + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::SetSubscribed(PRBool aSubscribed) +{ + if (aSubscribed) + { + m_isSubscribed = aSubscribed; + } + + return NS_OK; +} + + nsresult nsNNTPNewsgroup::GetWantNewTotals(PRBool *aWantNewTotals) +{ + if (aWantNewTotals) + { + *aWantNewTotals = m_wantsNewTotals; + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::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 nsNNTPNewsgroup::GetNewsgroupList(nsINNTPNewsgroupList * *aNewsgroupList) +{ + if (aNewsgroupList) + { + *aNewsgroupList = m_newsgroupList; + NS_IF_ADDREF(m_newsgroupList); + } + + return NS_OK; +} + +nsresult nsNNTPNewsgroup::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 nsNNTPNewsgroup::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; + nsNNTPNewsgroup * group = new nsNNTPNewsgroup(); + if (group) + { + group->SetSubscribed(subscribed); + rv = group->QueryInterface(nsINNTPNewsgroup::GetIID(), (void **) info); + } + + +#ifdef DEBUG_sspitzer + printf("NS_NewNewsgroup(%s)\n",line?line:"(null)"); +#endif + + if (line) { + group->SetName(line); + } + + return rv; +} + +} diff --git a/mailnews/news/src/nsNNTPNewsgroup.h b/mailnews/news/src/nsNNTPNewsgroup.h index 8d780c466f4..8a5267a06ce 100644 --- a/mailnews/news/src/nsNNTPNewsgroup.h +++ b/mailnews/news/src/nsNNTPNewsgroup.h @@ -33,5 +33,6 @@ NS_NewNewsgroup(nsINNTPNewsgroup **info, int depth); NS_END_EXTERN_C + #endif diff --git a/mailnews/news/src/nsNNTPNewsgroupList.cpp b/mailnews/news/src/nsNNTPNewsgroupList.cpp index f78147beb8f..bddcf47577c 100644 --- a/mailnews/news/src/nsNNTPNewsgroupList.cpp +++ b/mailnews/news/src/nsNNTPNewsgroupList.cpp @@ -43,9 +43,16 @@ class MessageDBView; #include "nsNNTPNewsgroupList.h" + #include "nsINNTPArticleList.h" #include "nsNNTPArticleSet.h" +#include "nsINNTPNewsgroup.h" +#include "nsNNTPNewsgroup.h" + +#include "nsINNTPHost.h" +#include "nsNNTPHost.h" + #include "msgCore.h" #include "plstr.h" @@ -66,6 +73,7 @@ class MessageDBView; #include "msgpane.h" #endif +#if 0 extern "C" { extern int MK_OUT_OF_MEMORY; @@ -73,6 +81,7 @@ extern "C" extern int MK_HDR_DOWNLOAD_COUNT; extern int MK_NO_NEW_DISC_MSGS; } +#endif extern PRInt32 net_NewsChunkSize; @@ -86,7 +95,7 @@ class nsNNTPNewsgroupList : public nsINNTPNewsgroupList #endif { public: - nsNNTPNewsgroupList(nsINNTPHost *, nsINNTPNewsgroup*); + nsNNTPNewsgroupList(nsINNTPHost *host, nsINNTPNewsgroup *newsgroup, const char *name, const char*url); nsNNTPNewsgroupList(); virtual ~nsNNTPNewsgroupList(); NS_DECL_ISUPPORTS @@ -102,16 +111,16 @@ public: // XOVER parser to populate this class NS_IMETHOD InitXOVER(PRInt32 first_msg, PRInt32 last_msg); - NS_IMETHOD ProcessXOVER(const char *line, PRUint32 * status); + NS_IMETHOD ProcessXOVERLINE(const char *line, PRUint32 * status); NS_IMETHOD ResetXOVER(); NS_IMETHOD ProcessNonXOVER(const char *line); - NS_IMETHOD FinishXOVER(int status, int *newstatus); + NS_IMETHOD FinishXOVERLINE(int status, int *newstatus); NS_IMETHOD ClearXOVERState(); + NS_IMETHOD GetGroupName(char **retval); private: - NS_METHOD Init(nsINNTPHost *, nsINNTPNewsgroup*) { return NS_OK;} - NS_METHOD InitNewsgroupList(const char *url, const char *groupName); + void Init(nsINNTPHost *host, nsINNTPNewsgroup *newsgroup, const char *name, const char *url); NS_METHOD CleanUp(); @@ -128,7 +137,6 @@ private: #endif PRBool m_finishingXover; nsINNTPHost* GetHost() {return m_host;} - const char * GetGroupName() {return m_groupName;} const char * GetURL() {return m_url;} #ifdef HAVE_CHANGELISTENER @@ -154,6 +162,7 @@ protected: PRInt32 m_maxArticles; char *m_groupName; nsINNTPHost *m_host; + nsINNTPNewsgroup *m_newsgroup; char *m_url; // url we're retrieving #ifdef HAVE_MASTER MSG_Master *m_master; @@ -173,10 +182,12 @@ protected: nsNNTPNewsgroupList::nsNNTPNewsgroupList(nsINNTPHost* host, - nsINNTPNewsgroup *newsgroup) + nsINNTPNewsgroup *newsgroup, + const char *name, + const char *url) { NS_INIT_REFCNT(); - Init(host, newsgroup); + Init(host, newsgroup, name, url); } @@ -186,11 +197,9 @@ nsNNTPNewsgroupList::~nsNNTPNewsgroupList() NS_IMPL_ISUPPORTS(nsNNTPNewsgroupList, nsINNTPNewsgroupList::GetIID()); -nsresult -nsNNTPNewsgroupList::InitNewsgroupList(const char *url, const char *groupName) -#ifdef HAVE_PANES -, MSG_Pane *pane); -#endif + +void +nsNNTPNewsgroupList::Init(nsINNTPHost *host, nsINNTPNewsgroup *newsgroup, const char *name, const char *url) { #ifdef HAVE_NEWSDB m_newsDB = NULL; @@ -198,7 +207,7 @@ nsNNTPNewsgroupList::InitNewsgroupList(const char *url, const char *groupName) #ifdef HAVE_DBVIEW m_msgDBView = NULL; #endif - m_groupName = PL_strdup(groupName); + m_groupName = PL_strdup(name); m_host = NULL; m_url = PL_strdup(url); m_lastProcessedNumber = 0; @@ -214,24 +223,16 @@ nsNNTPNewsgroupList::InitNewsgroupList(const char *url, const char *groupName) m_startedUpdate = PR_FALSE; memset(&m_knownArts, 0, sizeof(m_knownArts)); m_knownArts.group_name = m_groupName; -#ifdef HAVE_URLPARSER - char* host_and_port = NET_ParseURL(url, GET_HOST_PART); -#ifdef HAVE_MASTER - m_host = m_master->FindHost(host_and_port, - (url[0] == 's' || url[0] == 'S'), - -1); -#endif - PR_FREEIF(host_and_port); -#endif + m_host = host; + m_newsgroup = newsgroup; m_knownArts.host = m_host; + m_knownArts.set = nsNNTPArticleSet::Create(); m_getOldMessages = PR_FALSE; m_promptedAlready = PR_FALSE; m_downloadAll = PR_FALSE; m_maxArticles = 0; m_firstMsgToDownload = 0; m_lastMsgToDownload = 0; - - return NS_MSG_SUCCESS; } nsresult @@ -248,7 +249,10 @@ nsNNTPNewsgroupList::CleanUp() { if (m_newsDB) m_newsDB->Close(); #endif - delete m_knownArts.set; + if (m_knownArts.set) { + delete m_knownArts.set; + m_knownArts.set = nsnull; + } return NS_OK; } @@ -322,10 +326,16 @@ nsNNTPNewsgroupList::GetRangeOfArtsToDownload( newsGroupInfo->GetKnownArtsSet(knownArtsString); if (last_possible < newsGroupInfo->GetHighWater()) newsGroupInfo->SetHighWater(last_possible, TRUE); + if (m_knownArts.set) { + delete m_knownArts.set; + } m_knownArts.set = nsNNTPArticleSet::Create(knownArtsString); } else - { + { + if (m_knownArts.set) { + delete m_knownArts.set; + } m_knownArts.set = nsNNTPArticleSet::Create(); m_knownArts.set->AddRange(m_newsDB->GetLowWaterArticleNum(), m_newsDB->GetHighwaterArticleNum()); } @@ -476,11 +486,13 @@ nsNNTPNewsgroupList::AddToKnownArticles(PRInt32 first, PRInt32 last) m_knownArts.host = host; PR_FREEIF(m_knownArts.group_name); m_knownArts.group_name = PL_strdup(group_name); - delete m_knownArts.set; + if (m_knownArts.set) { + delete m_knownArts.set; + } m_knownArts.set = nsNNTPArticleSet::Create(); if (!m_knownArts.group_name || !m_knownArts.set) { - return MK_OUT_OF_MEMORY; + return NS_ERROR_OUT_OF_MEMORY; } } @@ -536,7 +548,7 @@ nsNNTPNewsgroupList::InitXOVER(PRInt32 first_msg, PRInt32 last_msg) #define NEWS_ART_DISPLAY_FREQ 10 nsresult -nsNNTPNewsgroupList::ProcessXOVER(const char *line, PRUint32 *status) +nsNNTPNewsgroupList::ProcessXOVERLINE(const char *line, PRUint32 *status) { const char *next; PRUint32 message_number=0; @@ -545,7 +557,7 @@ nsNNTPNewsgroupList::ProcessXOVER(const char *line, PRUint32 *status) PR_ASSERT (line); if (!line) - return NS_MSG_FAILURE; + return NS_ERROR_NULL_POINTER; #ifdef HAVE_DBVIEW if (m_msgDBView != NULL) @@ -671,7 +683,7 @@ nsNNTPNewsgroupList::ProcessNonXOVER (const char * /*line*/) nsresult -nsNNTPNewsgroupList::FinishXOVER (int status, int *newstatus) +nsNNTPNewsgroupList::FinishXOVERLINE(int status, int *newstatus) { struct MSG_NewsKnown* k; @@ -702,6 +714,11 @@ nsNNTPNewsgroupList::FinishXOVER (int status, int *newstatus) k = &m_knownArts; + if (k == nsnull) { + return NS_ERROR_NULL_POINTER; + } + + if (k->set) { PRInt32 n = k->set->FirstNonMember(); @@ -785,3 +802,25 @@ nsNNTPNewsgroupList::ClearXOVERState() return NS_OK; } +nsresult +nsNNTPNewsgroupList::GetGroupName(char **retval) +{ + *retval = m_groupName; + return NS_OK; +} + +extern "C" nsresult NS_NewNewsgroupList(nsINNTPNewsgroupList **aInstancePtrResult, + nsINNTPHost *newsHost, + nsINNTPNewsgroup *newsgroup, + const char *name, + const char *url) +{ + nsNNTPNewsgroupList *list = nsnull; + list = new nsNNTPNewsgroupList(newsHost, newsgroup, name, url); + if (list == nsnull) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = list->QueryInterface(nsINNTPNewsgroupList::GetIID(), (void **) aInstancePtrResult); + return rv; +} + diff --git a/mailnews/news/src/nsNNTPNewsgroupList.h b/mailnews/news/src/nsNNTPNewsgroupList.h index 3b195386fcc..55762c5b8ba 100644 --- a/mailnews/news/src/nsNNTPNewsgroupList.h +++ b/mailnews/news/src/nsNNTPNewsgroupList.h @@ -57,6 +57,8 @@ typedef struct MSG_NewsKnown { extern "C" nsresult NS_NewNewsgroupList(nsINNTPNewsgroupList **aInstancePtrResult, nsINNTPHost *newsHost, - nsINNTPNewsgroup *newsgroup); + nsINNTPNewsgroup *newsgroup, + const char *name, + const char *url); #endif diff --git a/mailnews/news/src/nsNNTPNewsgroupPost.cpp b/mailnews/news/src/nsNNTPNewsgroupPost.cpp index 3d68140933a..323537df47e 100644 --- a/mailnews/news/src/nsNNTPNewsgroupPost.cpp +++ b/mailnews/news/src/nsNNTPNewsgroupPost.cpp @@ -143,6 +143,8 @@ NS_IMPL_ISUPPORTS(nsNNTPNewsgroupPost, nsINNTPNewsgroupPost::GetIID()); nsNNTPNewsgroupPost::nsNNTPNewsgroupPost() { + NS_INIT_REFCNT(); + int i; for (i=0; i <= HEADER_LAST; i++) m_header[i]=nsnull; diff --git a/mailnews/news/src/nsNNTPProtocol.cpp b/mailnews/news/src/nsNNTPProtocol.cpp index e4949f3f041..2d64276c3cb 100644 --- a/mailnews/news/src/nsNNTPProtocol.cpp +++ b/mailnews/news/src/nsNNTPProtocol.cpp @@ -532,7 +532,20 @@ PRInt32 nsNNTPProtocol::LoadURL(nsIURL * aURL, nsISupports * aConsumer) { rv = NS_NewNNTPHost(&m_newsHost, hostAndPort, port ? port : NEWS_PORT); // save it on our url for future use.... + + if (NS_FAILED(rv) || (m_newsHost == nsnull)) { + status = -1; + goto FAIL; + } + m_runningURL->SetNntpHost(m_newsHost); + + // read in the newsrc file now, to build up the host correctly. + rv = m_newsHost->LoadNewsrc("news://news.mozilla.org"); + if (NS_FAILED(rv)) { + status = -1; + goto FAIL; + } } PR_ASSERT(NS_SUCCEEDED(rv)); @@ -1580,6 +1593,10 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) nsresult rv; nsINNTPNewsgroup *newsgroup; + if (m_newsHost == nsnull) { + printf("m_newsHost is null, panic!\n"); + return -1; + } rv = m_newsHost->GetNewsgroupAndNumberOfID(m_path, &newsgroup, &number); @@ -1618,7 +1635,11 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) { PRTime last_update; nsresult rv; - + + if (m_newsHost == nsnull) { + printf("m_newsHost is null, panic!\n"); + return -1; + } rv = m_newsHost->GetLastUpdatedTime(&last_update); char small_buf[64]; PRExplodedTime expandedTime; @@ -1634,7 +1655,7 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) last_update -= NEWGROUPS_TIME_OFFSET; { - int64 secToUSec, timeInSec, timeInUSec; + PRInt64 secToUSec, timeInSec, timeInUSec; LL_I2L(timeInSec, last_update); LL_I2L(secToUSec, PR_USEC_PER_SEC); LL_MUL(timeInUSec, timeInSec, secToUSec); @@ -1651,7 +1672,12 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) ClearFlag(NNTP_USE_FANCY_NEWSGROUP); PRTime last_update; - nsresult rv = m_newsHost->GetLastUpdatedTime(&last_update); + + if (m_newsHost == nsnull) { + printf("m_newsHost is null, panic!\n"); + return -1; + } + nsresult rv = m_newsHost->GetLastUpdatedTime(&last_update); if (NS_SUCCEEDED(rv) && last_update!=0) { @@ -1695,9 +1721,14 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) nsresult rv=NS_ERROR_NULL_POINTER; NET_SACopy(&command, "GROUP "); - if (m_newsgroup) - rv = m_newsgroup->GetName(&group_name); + if (m_newsgroup == nsnull) { + printf("m_newsgroup is null, panic!\n"); + return -1; + } + + rv = m_newsgroup->GetName(&group_name); slash = PL_strchr(group_name, '/'); + m_firstArticle = 0; m_lastArticle = 0; if (slash) @@ -1713,6 +1744,10 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) { nsresult rv; PRBool searchable=PR_FALSE; + if (m_newsHost == nsnull) { + printf("m_newsHost is null, panic!\n"); + return -1; + } rv = m_newsHost->QueryExtension("SEARCH", &searchable); if (NS_SUCCEEDED(rv) && searchable) { @@ -1737,6 +1772,10 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommand(nsIURL * url) /* for XPAT, we have to GROUP into the group before searching */ NET_SACopy(&command, "GROUP "); + if (m_newsgroup == nsnull) { + printf("m_newsgroup is null, panic!\n"); + return -1; + } rv = m_newsgroup->GetName(&group_name); NET_SACat (&command, group_name); m_nextState = NNTP_RESPONSE; @@ -2695,7 +2734,7 @@ PRInt32 nsNNTPProtocol::BeginReadXover() /* We now know there is a summary line there; make sure it has the right numbers in it. */ - char *group_name; + char *group_name = nsnull; m_newsgroup->GetName(&group_name); m_newsHost->DisplaySubscribedGroup(group_name, @@ -2703,6 +2742,7 @@ PRInt32 nsNNTPProtocol::BeginReadXover() m_lastPossibleArticle, count, PR_TRUE); PR_Free(group_name); + group_name = nsnull; if (status < 0) return status; m_numArticlesLoaded = 0; @@ -2725,19 +2765,23 @@ PRInt32 nsNNTPProtocol::FigureNextChunk() if (m_firstArticle > 0) { - nsresult rv; + nsresult rv = NS_OK; char *groupName; - nsINNTPNewsgroupList *newsgroupList; - - rv = m_newsgroup->GetName(&groupName); + + rv = m_newsgroup->GetName(&groupName); /* XXX - parse state stored in MSG_Pane cd->pane */ if (NS_SUCCEEDED(rv)) - rv = m_newsHost->GetNewsgroupList(groupName, &newsgroupList); + rv = m_newsHost->GetNewsgroupList(groupName, &m_newsgroupList); - if (NS_SUCCEEDED(rv)) - rv = newsgroupList->AddToKnownArticles(m_firstArticle, +#ifdef DEBUG_sspitzer + printf("add to known articles: %d - %d\n", m_firstArticle, m_lastArticle); +#endif + + if (NS_SUCCEEDED(rv) && m_newsgroupList != nsnull) { + rv = m_newsgroupList->AddToKnownArticles(m_firstArticle, m_lastArticle); - + } + if (NS_FAILED(rv)) { return status; @@ -2753,27 +2797,28 @@ PRInt32 nsNNTPProtocol::FigureNextChunk() } - char *groupName; - nsINNTPNewsgroupList *newsgroupList; + char *groupName = nsnull; - rv = m_newsgroup->GetName(&groupName); - if (NS_SUCCEEDED(rv)) - rv = m_newsHost->GetNewsgroupList(groupName, &newsgroupList); + if (m_newsgroupList == nsnull) { + rv = m_newsgroup->GetName(&groupName); + if (NS_SUCCEEDED(rv)) + rv = m_newsHost->GetNewsgroupList(groupName, &m_newsgroupList); + } - if (NS_SUCCEEDED(rv)) - rv = - newsgroupList->GetRangeOfArtsToDownload(m_firstPossibleArticle, + if (NS_SUCCEEDED(rv) && m_newsgroupList != nsnull) { + rv = m_newsgroupList->GetRangeOfArtsToDownload(m_firstPossibleArticle, m_lastPossibleArticle, m_numArticlesWanted - m_numArticlesLoaded, &(m_firstArticle), &(m_lastArticle), &status); - if (NS_FAILED(rv)) - { - return status; + } + if (NS_FAILED(rv)) { + return status; + } if (m_firstArticle <= 0 || m_firstArticle > m_lastArticle) { @@ -2788,9 +2833,9 @@ PRInt32 nsNNTPProtocol::FigureNextChunk() m_articleNumber = m_firstArticle; /* was MSG_InitXOVER() */ - rv = m_newsgroup->GetNewsgroupList(&m_newsgroupList); - if (NS_SUCCEEDED(rv)) + if (m_newsgroupList != nsnull) { rv = m_newsgroupList->InitXOVER(m_firstArticle, m_lastArticle); + } /* convert nsresult->status */ status = !NS_SUCCEEDED(rv); @@ -2818,7 +2863,9 @@ PRInt32 nsNNTPProtocol::XoverSend() m_firstArticle, m_lastArticle); - /* printf("XOVER %ld-%ld\n", m_firstArticle, m_lastArticle); */ +#ifdef DEBUG_sspitzer + printf("XOVER %ld-%ld\n", m_firstArticle, m_lastArticle); +#endif NNTP_LOG_WRITE(outputBuffer); @@ -2874,7 +2921,7 @@ PRInt32 nsNNTPProtocol::ReadXoverResponse() PRInt32 nsNNTPProtocol::ReadXover(nsIInputStream * inputStream, PRUint32 length) { - char *line; + char *line; nsresult rv; PRUint32 status = 1; @@ -2924,7 +2971,7 @@ PRInt32 nsNNTPProtocol::ReadXover(nsIInputStream * inputStream, PRUint32 length) #endif } - rv = m_newsgroupList->ProcessXOVER(line, &status); + rv = m_newsgroupList->ProcessXOVERLINE(line, &status); PR_ASSERT(NS_SUCCEEDED(rv)); m_numArticlesLoaded++; @@ -2941,8 +2988,13 @@ PRInt32 nsNNTPProtocol::ProcessXover() { nsresult rv; PRInt32 status = 0; + /* xover_parse_state stored in MSG_Pane cd->pane */ - rv = m_newsgroupList->FinishXOVER(0,&status); + if (m_newsgroupList == nsnull) { + return NS_ERROR_NULL_POINTER; + } + + rv = m_newsgroupList->FinishXOVERLINE(0,&status); if (NS_SUCCEEDED(rv) && status < 0) return status; @@ -4512,7 +4564,7 @@ PRInt32 nsNNTPProtocol::CloseConnection() int status; nsresult rv; /* XXX - how/when to Release() this? */ - rv = m_newsgroupList->FinishXOVER(status,&status); + rv = m_newsgroupList->FinishXOVERLINE(status,&status); PR_ASSERT(NS_SUCCEEDED(rv)); if (NS_SUCCEEDED(rv)) NS_RELEASE(m_newsgroupList); @@ -4527,7 +4579,7 @@ PRInt32 nsNNTPProtocol::CloseConnection() } #ifdef UNREADY_CODE if (cd->control_con) - cd->control_con->last_used_time = XP_TIME(); + cd->control_con->last_used_time = PR_Now(); #endif PR_FREEIF(m_path); diff --git a/mailnews/news/src/nsNntpService.cpp b/mailnews/news/src/nsNntpService.cpp index 32b0edfe990..fb7c10b6e99 100644 --- a/mailnews/news/src/nsNntpService.cpp +++ b/mailnews/news/src/nsNntpService.cpp @@ -23,17 +23,28 @@ #include // for InterlockedIncrement #endif - #include "nsNntpService.h" + #include "nsINetService.h" + #include "nsINntpUrl.h" #include "nsNNTPProtocol.h" +#include "nsNNTPNewsgroupPost.h" +#include "nsINetService.h" + +#include "nsIMsgMailSession.h" +#include "nsIMsgIdentity.h" + +#include "nsString2.h" + // we need this because of an egcs 1.0 (and possibly gcc) compiler bug // that doesn't allow you to call ::nsISupports::GetIID() inside of a class // that multiply inherits from nsISupports static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_CID(kNntpUrlCID, NS_NNTPURL_CID); +static NS_DEFINE_CID(kNetServiceCID, NS_NETSERVICE_CID); +static NS_DEFINE_CID(kCMsgMailSessionCID, NS_MSGMAILSESSION_CID); nsNntpService::nsNntpService() { @@ -51,16 +62,17 @@ nsresult nsNntpService::QueryInterface(const nsIID &aIID, void** aInstancePtr) if (nsnull == aInstancePtr) return NS_ERROR_NULL_POINTER; - if (aIID.Equals(nsINntpService::GetIID()) || aIID.Equals(kISupportsIID)) + if (aIID.Equals(nsINntpService::GetIID()) + || aIID.Equals(kISupportsIID)) { *aInstancePtr = (void*) ((nsINntpService*)this); - AddRef(); + NS_ADDREF_THIS(); return NS_OK; } if (aIID.Equals(nsIMsgMessageService::GetIID())) { *aInstancePtr = (void*) ((nsIMsgMessageService*)this); - AddRef(); + NS_ADDREF_THIS(); return NS_OK; } @@ -82,16 +94,16 @@ nsresult nsNntpService::QueryInterface(const nsIID &aIID, void** aInstancePtr) nsresult nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aDisplayConsumer, nsIUrlListener * aUrlListener, nsIURL ** aURL) { - // this function is just a shell right now....eventually we'll implement displaymessage such - // that we break down the URI and extract the news host and article number. We'll then - // build up a url that represents that action, create a connection to run the url - // and load the url into the connection. - - // HACK ALERT: For now, the only news url we run is a display message url. So just forward - // this URI to RunNewUrl - - return RunNewsUrl(aMessageURI, aDisplayConsumer, aUrlListener, aURL); + // this function is just a shell right now....eventually we'll implement displaymessage such + // that we break down the URI and extract the news host and article number. We'll then + // build up a url that represents that action, create a connection to run the url + // and load the url into the connection. + + // HACK ALERT: For now, the only news url we run is a display message url. So just forward + // this URI to RunNewUrl + nsString uri = aMessageURI; + return RunNewsUrl(uri, aDisplayConsumer, aUrlListener, aURL); } nsresult nsNntpService::CopyMessage(const char * aSrcMailboxURI, nsIStreamListener * aMailboxCopyHandler, PRBool moveMessage, @@ -104,9 +116,53 @@ nsresult nsNntpService::CopyMessage(const char * aSrcMailboxURI, nsIStreamListen //////////////////////////////////////////////////////////////////////////////////////// // nsINntpService support //////////////////////////////////////////////////////////////////////////////////////// +nsresult nsNntpService::PostMessage(nsFilePath &pathToFile, const char *subject, const char *newsgroup, nsIUrlListener * aUrlListener, nsIURL ** aURL) +{ + nsresult rv = NS_OK; -NS_IMETHODIMP nsNntpService::RunNewsUrl(const nsString& urlString, nsISupports * aConsumer, - nsIUrlListener *aUrlListener, nsIURL ** aUrl) +#ifdef DEBUG_sspitzer + printf("nsNntpService::PostMessage(%s,%s,%s,??,??)\n",(const char *)pathToFile,subject,newsgroup); +#endif + + NS_LOCK_INSTANCE(); + + // get the current identity from the news session.... + NS_WITH_SERVICE(nsIMsgMailSession,newsSession,kCMsgMailSessionCID,&rv); + + if (NS_SUCCEEDED(rv) && newsSession) + { + nsIMsgIdentity * identity = nsnull; + rv = newsSession->GetCurrentIdentity(&identity); + + if (NS_SUCCEEDED(rv) && identity) + { + char * fullname = nsnull; + char * email = nsnull; + char * organization = nsnull; + + identity->GetFullName(&fullname); + identity->GetEmail(&email); + identity->GetOrganization(&organization); + +#ifdef DEBUG_sspitzer + printf("post message as: %s,%s,%s\n",fullname,email,organization); +#endif + + // todo: are we leaking fullname, email and organization? + + // release the identity + NS_IF_RELEASE(identity); + } // if we have an identity + else + NS_ASSERTION(0, "no current identity found for this user...."); + } // if we had a news session + + NS_UNLOCK_INSTANCE(); + return rv; +} + +nsresult nsNntpService::RunNewsUrl(const nsString& urlString, nsISupports * aConsumer, + nsIUrlListener *aUrlListener, nsIURL ** aURL) { // for now, assume the url is a news url and load it.... nsINntpUrl *nntpUrl = nsnull; @@ -147,10 +203,12 @@ NS_IMETHODIMP nsNntpService::RunNewsUrl(const nsString& urlString, nsISupports * nntpProtocol = new nsNNTPProtocol(nntpUrl, transport); if (nntpProtocol) nntpProtocol->LoadURL(nntpUrl, aConsumer); + + //delete nntpProtocol; } - if (aUrl) - *aUrl = nntpUrl; // transfer ref count + if (aURL) + *aURL = nntpUrl; // transfer ref count else NS_RELEASE(nntpUrl); } // if nntpUrl diff --git a/mailnews/news/src/nsNntpService.h b/mailnews/news/src/nsNntpService.h index 6ad0490416b..3038460aead 100644 --- a/mailnews/news/src/nsNntpService.h +++ b/mailnews/news/src/nsNntpService.h @@ -39,6 +39,8 @@ public: NS_IMETHOD RunNewsUrl (const nsString& urlString, nsISupports * aConsumer, nsIUrlListener * aUrlListener, nsIURL ** aURL); + NS_IMETHOD PostMessage (nsFilePath &pathToFile, const char *subject, const char *newsgroup, nsIUrlListener * aUrlListener, nsIURL ** aURL); + //////////////////////////////////////////////////////////////////////////////////////// // we suppport the nsIMsgMessageService Interface //////////////////////////////////////////////////////////////////////////////////////// diff --git a/mailnews/news/src/nsNntpUrl.cpp b/mailnews/news/src/nsNntpUrl.cpp index 1f14dd45540..bfd60f91d57 100644 --- a/mailnews/news/src/nsNntpUrl.cpp +++ b/mailnews/news/src/nsNntpUrl.cpp @@ -849,6 +849,11 @@ nsresult nsNntpUrl::GetSpec(const char* *result) const nsresult nsNntpUrl::SetSpec(const char *aNewSpec) { +#ifdef DEBUG_sspitzer + if (aNewSpec) { + printf("nsNntpUrl::SetSpec(%s)\n", aNewSpec); + } +#endif // XXX is this right, or should we call ParseURL? nsresult rv = NS_OK; // NS_ASSERTION(m_URL_s == nsnull, "URL has already been opened");