Example #1
0
void ListBinCommand::Execute()
{
	SNZBListRequest ListRequest;
	if (!ReceiveRequest(&ListRequest, sizeof(ListRequest)))
	{
		return;
	}

	SNZBListResponse ListResponse;
	memset(&ListResponse, 0, sizeof(ListResponse));
	ListResponse.m_MessageBase.m_iSignature = htonl(NZBMESSAGE_SIGNATURE);
	ListResponse.m_MessageBase.m_iStructSize = htonl(sizeof(ListResponse));
	ListResponse.m_iEntrySize = htonl(sizeof(SNZBListResponseFileEntry));
	ListResponse.m_bRegExValid = 0;

	char* buf = NULL;
	int bufsize = 0;

	if (ntohl(ListRequest.m_bFileList))
	{
		eRemoteMatchMode eMatchMode = (eRemoteMatchMode)ntohl(ListRequest.m_iMatchMode);
		bool bMatchGroup = ntohl(ListRequest.m_bMatchGroup);
		const char* szPattern = ListRequest.m_szPattern;

		RegEx *pRegEx = NULL;
		if (eMatchMode == eRemoteMatchModeRegEx)
		{
			pRegEx = new RegEx(szPattern);
			ListResponse.m_bRegExValid = pRegEx->IsValid();
		}

		// Make a data structure and copy all the elements of the list into it
		DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();

		// calculate required buffer size for nzbs
		int iNrNZBEntries = pDownloadQueue->GetNZBInfoList()->size();
		int iNrPPPEntries = 0;
		bufsize += iNrNZBEntries * sizeof(SNZBListResponseNZBEntry);
		for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
		{
			NZBInfo* pNZBInfo = *it;
			bufsize += strlen(pNZBInfo->GetFilename()) + 1;
			bufsize += strlen(pNZBInfo->GetName()) + 1;
			bufsize += strlen(pNZBInfo->GetDestDir()) + 1;
			bufsize += strlen(pNZBInfo->GetCategory()) + 1;
			bufsize += strlen(pNZBInfo->GetQueuedFilename()) + 1;
			// align struct to 4-bytes, needed by ARM-processor (and may be others)
			bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;

			// calculate required buffer size for pp-parameters
			for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++)
			{
				NZBParameter* pNZBParameter = *it;
				bufsize += sizeof(SNZBListResponsePPPEntry);
				bufsize += strlen(pNZBParameter->GetName()) + 1;
				bufsize += strlen(pNZBParameter->GetValue()) + 1;
				// align struct to 4-bytes, needed by ARM-processor (and may be others)
				bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
				iNrPPPEntries++;
			}
		}

		// calculate required buffer size for files
		int iNrFileEntries = pDownloadQueue->GetFileQueue()->size();
		bufsize += iNrFileEntries * sizeof(SNZBListResponseFileEntry);
		for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
		{
			FileInfo* pFileInfo = *it;
			bufsize += strlen(pFileInfo->GetSubject()) + 1;
			bufsize += strlen(pFileInfo->GetFilename()) + 1;
			// align struct to 4-bytes, needed by ARM-processor (and may be others)
			bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
		}

		buf = (char*) malloc(bufsize);
		char* bufptr = buf;

		// write nzb entries
		for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
		{
			unsigned long iSizeHi, iSizeLo;
			NZBInfo* pNZBInfo = *it;
			SNZBListResponseNZBEntry* pListAnswer = (SNZBListResponseNZBEntry*) bufptr;
			Util::SplitInt64(pNZBInfo->GetSize(), &iSizeHi, &iSizeLo);
			pListAnswer->m_iSizeLo				= htonl(iSizeLo);
			pListAnswer->m_iSizeHi				= htonl(iSizeHi);
			pListAnswer->m_bMatch				= htonl(bMatchGroup && (!pRegEx || pRegEx->Match(pNZBInfo->GetName())));
			pListAnswer->m_iFilenameLen			= htonl(strlen(pNZBInfo->GetFilename()) + 1);
			pListAnswer->m_iNameLen				= htonl(strlen(pNZBInfo->GetName()) + 1);
			pListAnswer->m_iDestDirLen			= htonl(strlen(pNZBInfo->GetDestDir()) + 1);
			pListAnswer->m_iCategoryLen			= htonl(strlen(pNZBInfo->GetCategory()) + 1);
			pListAnswer->m_iQueuedFilenameLen	= htonl(strlen(pNZBInfo->GetQueuedFilename()) + 1);
			bufptr += sizeof(SNZBListResponseNZBEntry);
			strcpy(bufptr, pNZBInfo->GetFilename());
			bufptr += ntohl(pListAnswer->m_iFilenameLen);
			strcpy(bufptr, pNZBInfo->GetName());
			bufptr += ntohl(pListAnswer->m_iNameLen);
			strcpy(bufptr, pNZBInfo->GetDestDir());
			bufptr += ntohl(pListAnswer->m_iDestDirLen);
			strcpy(bufptr, pNZBInfo->GetCategory());
			bufptr += ntohl(pListAnswer->m_iCategoryLen);
			strcpy(bufptr, pNZBInfo->GetQueuedFilename());
			bufptr += ntohl(pListAnswer->m_iQueuedFilenameLen);
			// align struct to 4-bytes, needed by ARM-processor (and may be others)
			if ((size_t)bufptr % 4 > 0)
			{
				pListAnswer->m_iQueuedFilenameLen = htonl(ntohl(pListAnswer->m_iQueuedFilenameLen) + 4 - (size_t)bufptr % 4);
				memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
				bufptr += 4 - (size_t)bufptr % 4;
			}
		}

		// write ppp entries
		int iNZBIndex = 1;
		for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++, iNZBIndex++)
		{
			NZBInfo* pNZBInfo = *it;
			for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++)
			{
				NZBParameter* pNZBParameter = *it;
				SNZBListResponsePPPEntry* pListAnswer = (SNZBListResponsePPPEntry*) bufptr;
				pListAnswer->m_iNZBIndex	= htonl(iNZBIndex);
				pListAnswer->m_iNameLen		= htonl(strlen(pNZBParameter->GetName()) + 1);
				pListAnswer->m_iValueLen	= htonl(strlen(pNZBParameter->GetValue()) + 1);
				bufptr += sizeof(SNZBListResponsePPPEntry);
				strcpy(bufptr, pNZBParameter->GetName());
				bufptr += ntohl(pListAnswer->m_iNameLen);
				strcpy(bufptr, pNZBParameter->GetValue());
				bufptr += ntohl(pListAnswer->m_iValueLen);
				// align struct to 4-bytes, needed by ARM-processor (and may be others)
				if ((size_t)bufptr % 4 > 0)
				{
					pListAnswer->m_iValueLen = htonl(ntohl(pListAnswer->m_iValueLen) + 4 - (size_t)bufptr % 4);
					memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
					bufptr += 4 - (size_t)bufptr % 4;
				}
			}
		}

		// write file entries
		for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
		{
			unsigned long iSizeHi, iSizeLo;
			FileInfo* pFileInfo = *it;
			SNZBListResponseFileEntry* pListAnswer = (SNZBListResponseFileEntry*) bufptr;
			pListAnswer->m_iID = htonl(pFileInfo->GetID());

			int iNZBIndex = 0;
			for (unsigned int i = 0; i < pDownloadQueue->GetNZBInfoList()->size(); i++)
			{
				iNZBIndex++;
				if (pDownloadQueue->GetNZBInfoList()->at(i) == pFileInfo->GetNZBInfo())
				{
					break;
				}
			}
			pListAnswer->m_iNZBIndex		= htonl(iNZBIndex);

			if (pRegEx && !bMatchGroup)
			{
				char szFilename[MAX_PATH];
				snprintf(szFilename, sizeof(szFilename) - 1, "%s/%s", pFileInfo->GetNZBInfo()->GetName(), Util::BaseFileName(pFileInfo->GetFilename()));
				pListAnswer->m_bMatch = htonl(pRegEx->Match(szFilename));
			}

			Util::SplitInt64(pFileInfo->GetSize(), &iSizeHi, &iSizeLo);
			pListAnswer->m_iFileSizeLo		= htonl(iSizeLo);
			pListAnswer->m_iFileSizeHi		= htonl(iSizeHi);
			Util::SplitInt64(pFileInfo->GetRemainingSize(), &iSizeHi, &iSizeLo);
			pListAnswer->m_iRemainingSizeLo	= htonl(iSizeLo);
			pListAnswer->m_iRemainingSizeHi	= htonl(iSizeHi);
			pListAnswer->m_bFilenameConfirmed = htonl(pFileInfo->GetFilenameConfirmed());
			pListAnswer->m_bPaused			= htonl(pFileInfo->GetPaused());
			pListAnswer->m_iActiveDownloads	= htonl(pFileInfo->GetActiveDownloads());
			pListAnswer->m_iPriority		= htonl(pFileInfo->GetPriority());
			pListAnswer->m_iSubjectLen		= htonl(strlen(pFileInfo->GetSubject()) + 1);
			pListAnswer->m_iFilenameLen		= htonl(strlen(pFileInfo->GetFilename()) + 1);
			bufptr += sizeof(SNZBListResponseFileEntry);
			strcpy(bufptr, pFileInfo->GetSubject());
			bufptr += ntohl(pListAnswer->m_iSubjectLen);
			strcpy(bufptr, pFileInfo->GetFilename());
			bufptr += ntohl(pListAnswer->m_iFilenameLen);
			// align struct to 4-bytes, needed by ARM-processor (and may be others)
			if ((size_t)bufptr % 4 > 0)
			{
				pListAnswer->m_iFilenameLen = htonl(ntohl(pListAnswer->m_iFilenameLen) + 4 - (size_t)bufptr % 4);
				memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
				bufptr += 4 - (size_t)bufptr % 4;
			}
		}

		g_pQueueCoordinator->UnlockQueue();

		if (pRegEx)
		{
			delete pRegEx;
		}

		ListResponse.m_iNrTrailingNZBEntries = htonl(iNrNZBEntries);
		ListResponse.m_iNrTrailingPPPEntries = htonl(iNrPPPEntries);
		ListResponse.m_iNrTrailingFileEntries = htonl(iNrFileEntries);
		ListResponse.m_iTrailingDataLength = htonl(bufsize);
	}

	if (htonl(ListRequest.m_bServerState))
	{
		unsigned long iSizeHi, iSizeLo;
		ListResponse.m_iDownloadRate = htonl((int)(g_pQueueCoordinator->CalcCurrentDownloadSpeed() * 1024));
		Util::SplitInt64(g_pQueueCoordinator->CalcRemainingSize(), &iSizeHi, &iSizeLo);
		ListResponse.m_iRemainingSizeHi = htonl(iSizeHi);
		ListResponse.m_iRemainingSizeLo = htonl(iSizeLo);
		ListResponse.m_iDownloadLimit = htonl((int)(g_pOptions->GetDownloadRate() * 1024));
		ListResponse.m_bDownloadPaused = htonl(g_pOptions->GetPauseDownload());
		ListResponse.m_bDownload2Paused = htonl(g_pOptions->GetPauseDownload2());
		ListResponse.m_bPostPaused = htonl(g_pOptions->GetPausePostProcess());
		ListResponse.m_bScanPaused = htonl(g_pOptions->GetPauseScan());
		ListResponse.m_iThreadCount = htonl(Thread::GetThreadCount() - 1); // not counting itself
		PostQueue* pPostQueue = g_pQueueCoordinator->LockQueue()->GetPostQueue();
		ListResponse.m_iPostJobCount = htonl(pPostQueue->size());
		g_pQueueCoordinator->UnlockQueue();

		int iUpTimeSec, iDnTimeSec;
		long long iAllBytes;
		bool bStandBy;
		g_pQueueCoordinator->CalcStat(&iUpTimeSec, &iDnTimeSec, &iAllBytes, &bStandBy);
		ListResponse.m_iUpTimeSec = htonl(iUpTimeSec);
		ListResponse.m_iDownloadTimeSec = htonl(iDnTimeSec);
		ListResponse.m_bDownloadStandBy = htonl(bStandBy);
		Util::SplitInt64(iAllBytes, &iSizeHi, &iSizeLo);
		ListResponse.m_iDownloadedBytesHi = htonl(iSizeHi);
		ListResponse.m_iDownloadedBytesLo = htonl(iSizeLo);
	}

	// Send the request answer
	send(m_iSocket, (char*) &ListResponse, sizeof(ListResponse), 0);

	// Send the data
	if (bufsize > 0)
	{
		send(m_iSocket, buf, bufsize, 0);
	}

	if (buf)
	{
		free(buf);
	}
}
void HistoryCoordinator::HistoryRedownload(DownloadQueue* pDownloadQueue, HistoryList::iterator itHistory,
	HistoryInfo* pHistoryInfo, bool bRestorePauseState)
{
	if (pHistoryInfo->GetKind() == HistoryInfo::hkUrl)
	{
		HistoryReturn(pDownloadQueue, itHistory, pHistoryInfo, false);
		return;
	}

	if (pHistoryInfo->GetKind() != HistoryInfo::hkNzb)
	{
		char szNiceName[1024];
		pHistoryInfo->GetName(szNiceName, 1024);
		error("Could not return %s from history back to queue: history item has wrong type", szNiceName);
		return;
	}

	NZBInfo* pNZBInfo = pHistoryInfo->GetNZBInfo();
	bool bPaused = bRestorePauseState && pNZBInfo->GetDeletePaused();

	if (!Util::FileExists(pNZBInfo->GetQueuedFilename()))
	{
		error("Could not return %s from history back to queue: could not find source nzb-file %s",
			pNZBInfo->GetName(), pNZBInfo->GetQueuedFilename());
		return;
	}

	NZBFile* pNZBFile = new NZBFile(pNZBInfo->GetQueuedFilename(), "");
	if (!pNZBFile->Parse())
	{
		error("Could not return %s from history back to queue: could not parse nzb-file",
			pNZBInfo->GetName());
		delete pNZBFile;
		return;
	}

	info("Returning %s from history back to queue", pNZBInfo->GetName());

	for (FileList::iterator it = pNZBFile->GetNZBInfo()->GetFileList()->begin(); it != pNZBFile->GetNZBInfo()->GetFileList()->end(); it++)
	{
		FileInfo* pFileInfo = *it;
		pFileInfo->SetPaused(bPaused);
	}

	if (Util::DirectoryExists(pNZBInfo->GetDestDir()))
	{
		detail("Deleting %s", pNZBInfo->GetDestDir());
		char szErrBuf[256];
		if (!Util::DeleteDirectoryWithContent(pNZBInfo->GetDestDir(), szErrBuf, sizeof(szErrBuf)))
		{
			error("Could not delete directory %s: %s", pNZBInfo->GetDestDir(), szErrBuf);
		}
	}

	pNZBInfo->BuildDestDirName();
	if (Util::DirectoryExists(pNZBInfo->GetDestDir()))
	{
		detail("Deleting %s", pNZBInfo->GetDestDir());
		char szErrBuf[256];
		if (!Util::DeleteDirectoryWithContent(pNZBInfo->GetDestDir(), szErrBuf, sizeof(szErrBuf)))
		{
			error("Could not delete directory %s: %s", pNZBInfo->GetDestDir(), szErrBuf);
		}
	}

	g_pDiskState->DiscardFiles(pNZBInfo);

	// reset status fields (which are not reset by "HistoryReturn")
	pNZBInfo->SetMoveStatus(NZBInfo::msNone);
	pNZBInfo->SetUnpackCleanedUpDisk(false);
	pNZBInfo->SetParStatus(NZBInfo::psNone);
	pNZBInfo->SetRenameStatus(NZBInfo::rsNone);
	pNZBInfo->SetDownloadedSize(0);
	pNZBInfo->SetDownloadSec(0);
	pNZBInfo->SetPostTotalSec(0);
	pNZBInfo->SetParSec(0);
	pNZBInfo->SetRepairSec(0);
	pNZBInfo->SetUnpackSec(0);
	pNZBInfo->SetExtraParBlocks(0);
	pNZBInfo->ClearCompletedFiles();
	pNZBInfo->GetServerStats()->Clear();
	pNZBInfo->GetCurrentServerStats()->Clear();

	pNZBInfo->CopyFileList(pNZBFile->GetNZBInfo());

	g_pQueueCoordinator->CheckDupeFileInfos(pNZBInfo);
	delete pNZBFile;

	HistoryReturn(pDownloadQueue, itHistory, pHistoryInfo, false);

	g_pPrePostProcessor->NZBAdded(pDownloadQueue, pNZBInfo);
}
Example #3
0
void QueueCoordinator::AddNZBFileToQueue(NZBFile* pNZBFile, NZBInfo* pUrlInfo, bool bAddFirst)
{
    debug("Adding NZBFile to queue");

    NZBInfo* pNZBInfo = pNZBFile->GetNZBInfo();

    DownloadQueue* pDownloadQueue = DownloadQueue::Lock();

    DownloadQueue::Aspect foundAspect = { DownloadQueue::eaNzbFound, pDownloadQueue, pNZBInfo, NULL };
    pDownloadQueue->Notify(&foundAspect);

    NZBInfo::EDeleteStatus eDeleteStatus = pNZBInfo->GetDeleteStatus();

    if (eDeleteStatus != NZBInfo::dsNone)
    {
        bool bAllPaused = !pNZBInfo->GetFileList()->empty();
        for (FileList::iterator it = pNZBInfo->GetFileList()->begin(); it != pNZBInfo->GetFileList()->end(); it++)
        {
            FileInfo* pFileInfo = *it;
            bAllPaused &= pFileInfo->GetPaused();
            if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
            {
                g_pDiskState->DiscardFile(pFileInfo, true, false, false);
            }
        }
        pNZBInfo->SetDeletePaused(bAllPaused);
    }

    if (eDeleteStatus != NZBInfo::dsManual)
    {
        // NZBInfo will be added either to queue or to history as duplicate
        // and therefore can be detached from NZBFile.
        pNZBFile->DetachNZBInfo();
    }

    if (eDeleteStatus == NZBInfo::dsNone)
    {
        if (g_pOptions->GetDupeCheck() && pNZBInfo->GetDupeMode() != dmForce)
        {
            CheckDupeFileInfos(pNZBInfo);
        }

        if (pUrlInfo)
        {
            // insert at the URL position
            for (NZBList::iterator it = pDownloadQueue->GetQueue()->begin(); it != pDownloadQueue->GetQueue()->end(); it++)
            {
                NZBInfo* pPosNzbInfo = *it;
                if (pPosNzbInfo == pUrlInfo)
                {
                    pDownloadQueue->GetQueue()->insert(it, pNZBInfo);
                    break;
                }
            }
        }
        else if (bAddFirst)
        {
            pDownloadQueue->GetQueue()->push_front(pNZBInfo);
        }
        else
        {
            pDownloadQueue->GetQueue()->push_back(pNZBInfo);
        }
    }

    if (pUrlInfo)
    {
        pNZBInfo->SetID(pUrlInfo->GetID());
        pDownloadQueue->GetQueue()->Remove(pUrlInfo);
        delete pUrlInfo;
    }

    if (eDeleteStatus == NZBInfo::dsNone)
    {
        pNZBInfo->PrintMessage(Message::mkInfo, "Collection %s added to queue", pNZBInfo->GetName());
    }

    if (eDeleteStatus != NZBInfo::dsManual)
    {
        DownloadQueue::Aspect addedAspect = { DownloadQueue::eaNzbAdded, pDownloadQueue, pNZBInfo, NULL };
        pDownloadQueue->Notify(&addedAspect);
    }

    pDownloadQueue->Save();

    DownloadQueue::Unlock();
}