/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include "msg.h" #include "msgdwnof.h" #include "pmsgsrch.h" #include "msgfinfo.h" #include "msgurlq.h" #include "nwsartst.h" #include "newsdb.h" #include "listngst.h" extern "C" { extern int MK_OUT_OF_MEMORY; } MSG_DownloadOfflineFoldersState::MSG_DownloadOfflineFoldersState(MSG_Pane *pane) { m_folderIterator = new MSG_FolderIterator(pane->GetMaster()->GetFolderTree()); m_pane = pane; m_newsDB = NULL; m_oneFolder = FALSE; m_foundFolderToDownload = FALSE; m_curFolder = NULL; } MSG_DownloadOfflineFoldersState::~MSG_DownloadOfflineFoldersState() { delete m_folderIterator; } int MSG_DownloadOfflineFoldersState::DoIt() { return DoSomeMore(); } /* static */int MSG_DownloadOfflineFoldersState::FolderDoneCB(void *state, int /* status */) { MSG_DownloadOfflineFoldersState *downloadState = (MSG_DownloadOfflineFoldersState *) state; return downloadState->DoSomeMore(); } int MSG_DownloadOfflineFoldersState::DownloadOneFolder(MSG_FolderInfo *folder) { m_oneFolder = TRUE; m_folderIterator->AdvanceToFolder(folder); return DownloadFolder(folder); } int MSG_DownloadOfflineFoldersState::DownloadFolder(MSG_FolderInfo *folder) { char *url = folder->BuildUrl(NULL, MSG_MESSAGEKEYNONE); if (!url) return eOUT_OF_MEMORY; m_curFolder = folder; MSG_FolderInfoNews *newsFolder = folder->GetNewsFolderInfo(); XP_ASSERT(newsFolder); const char* groupname = newsFolder->GetNewsgroupName(); MSG_Master *master = m_pane->GetMaster(); URL_Struct *url_struct; url_struct = NET_CreateURLStruct(url, NET_DONT_RELOAD); ListNewsGroupState * listState = new ListNewsGroupState(url, groupname, m_pane); XPPtrArray referringPanes; master->FindPanesReferringToFolder(newsFolder, &referringPanes); for (int i = 0; i < referringPanes.GetSize(); i++) { MSG_Pane *pane = (MSG_Pane *) referringPanes.GetAt(i); if (pane && pane->GetMsgView()) { listState->SetView(pane->GetMsgView()); break; } } listState->SetMaster(master); listState->SetGetOldMessages(FALSE); // get messages below highwater mark if we don't have them newsFolder->SetListNewsGroupState(listState); url_struct->fe_data = this; url_struct->msg_pane = m_pane; MSG_UrlQueue::AddUrlToPane (url_struct, MSG_DownloadOfflineFoldersState::DownloadArticlesCB, m_pane, TRUE, FO_PRESENT); return eSUCCESS; } /* static */ void MSG_DownloadOfflineFoldersState::DownloadArticlesCB(URL_Struct *url , int status, MWContext * /* context */) { if (status != MK_INTERRUPTED) { MSG_DownloadOfflineFoldersState *downloadState = (MSG_DownloadOfflineFoldersState *) url->fe_data; XP_ASSERT (downloadState); if (downloadState) downloadState->DownloadArticles(downloadState->GetCurFolder()); } #ifdef DEBUG_bienvenu else XP_Trace("download articles interrupted\n"); #endif } int MSG_DownloadOfflineFoldersState::DownloadArticles(MSG_FolderInfo *curFolder) { XP_Bool useDefaults, byReadness, unreadOnly, byDate; int32 daysOld; int ret = 0; MSG_GetOfflineRetrievalInfo(curFolder, &useDefaults, &byReadness, &unreadOnly, &byDate, &daysOld); if (useDefaults) { // ### dmb find preferences! Change local variables above based on them. } MSG_SearchTermArray termArray; MSG_SearchValue value; if (byReadness && unreadOnly) { value.attribute = attribMsgStatus; value.u.msgStatus = kIsRead; termArray.Add(new MSG_SearchTerm(attribMsgStatus, opIsnt, &value, MSG_SearchBooleanAND, NULL)); } if (byDate) { value.attribute = attribAgeInDays; value.u.age = daysOld; termArray.Add(new MSG_SearchTerm(attribAgeInDays, opIsLessThan, &value, MSG_SearchBooleanAND, NULL)); } if (termArray.GetSize() == 0) // cons up a search term that will match every msg we need { value.attribute = attribMsgStatus; value.u.msgStatus = kOffline; termArray.Add(new MSG_SearchTerm(attribMsgStatus, opIsnt, &value, MSG_SearchBooleanAND, NULL)); } char *url = curFolder->BuildUrl(NULL, MSG_MESSAGEKEYNONE); if (!url) return MK_OUT_OF_MEMORY; MsgERR err = NewsGroupDB::Open(url, m_pane->GetMaster(), &m_newsDB); if (err == eSUCCESS) ret = DownloadMatchingNewsArticlesToNewsDB::SaveMatchingMessages(m_pane->GetContext(), curFolder, m_newsDB, termArray, FolderDoneCB, this); for (int32 index = 0; index < termArray.GetSize(); index++) { MSG_SearchTerm *doomedSearchTerm = termArray.GetAt(index); if (doomedSearchTerm) delete doomedSearchTerm; } return ret; } int MSG_DownloadOfflineFoldersState::DoSomeMore() { int ret = 0; MSG_FolderInfo *nextFolder = m_folderIterator->Next(); XP_Bool prevFolderWasCategory = (m_curFolder) ? (m_curFolder->GetFlags() & MSG_FOLDER_FLAG_CATEGORY) != 0 : FALSE; if (m_newsDB != NULL) m_newsDB->Close(); m_newsDB = NULL; if (m_oneFolder && !prevFolderWasCategory) // if we're only doing one folder, we're done. return ret; while (nextFolder) { MSG_FolderInfo *nextCategoryContainer = (prevFolderWasCategory) ? MSG_GetCategoryContainerForCategory(nextFolder) : 0; uint32 folderPrefFlags = (nextCategoryContainer) ? nextCategoryContainer->GetFolderPrefFlags() : nextFolder->GetFolderPrefFlags(); // if we're doing one folder, and the category container has changed, we're done if (m_oneFolder && prevFolderWasCategory && nextCategoryContainer != MSG_GetCategoryContainerForCategory(m_curFolder)) return ret; MSG_FolderInfoNews *newsFolder = nextFolder->GetNewsFolderInfo(); if (newsFolder && newsFolder->IsSubscribed() && ((folderPrefFlags & MSG_FOLDER_PREF_OFFLINE) != 0) || m_oneFolder) { ret = DownloadFolder(nextFolder); m_foundFolderToDownload = TRUE; break; } else nextFolder = m_folderIterator->Next(); } ret = (m_foundFolderToDownload) ? ret : -1; // didn't find one folder! if (nextFolder == NULL || ret == MK_CONNECTED) { if (m_pane && m_pane->GetURLChain()) m_pane->GetURLChain()->GetNextURL(); delete this; // would be nice to do this at a higher level. } return ret; }