/** * If szStripPrefix is not NULL, only pp-parameters, whose names start with the prefix * are processed. The prefix is then stripped from the names. * If szStripPrefix is NULL, all pp-parameters are processed; without stripping. */ void NZBScriptController::PrepareEnvParameters(NZBParameterList* pParameters, const char* szStripPrefix) { int iPrefixLen = szStripPrefix ? strlen(szStripPrefix) : 0; for (NZBParameterList::iterator it = pParameters->begin(); it != pParameters->end(); it++) { NZBParameter* pParameter = *it; const char* szValue = pParameter->GetValue(); #ifdef WIN32 char* szAnsiValue = strdup(szValue); WebUtil::Utf8ToAnsi(szAnsiValue, strlen(szAnsiValue) + 1); szValue = szAnsiValue; #endif if (szStripPrefix && !strncmp(pParameter->GetName(), szStripPrefix, iPrefixLen) && (int)strlen(pParameter->GetName()) > iPrefixLen) { SetEnvVarSpecial("NZBPR", pParameter->GetName() + iPrefixLen, szValue); } else if (!szStripPrefix) { SetEnvVarSpecial("NZBPR", pParameter->GetName(), szValue); } #ifdef WIN32 free(szAnsiValue); #endif } }
void PrePostProcessor::StartJob(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo) { #ifndef DISABLE_PARCHECK if (pPostInfo->GetNZBInfo()->GetRenameStatus() == NZBInfo::rsNone) { UpdatePauseState(g_pOptions->GetParPauseQueue(), "par-rename"); m_ParCoordinator.StartParRenameJob(pPostInfo); return; } else if (pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psNone) { if (m_ParCoordinator.FindMainPars(pPostInfo->GetNZBInfo()->GetDestDir(), NULL)) { UpdatePauseState(g_pOptions->GetParPauseQueue(), "par-check"); m_ParCoordinator.StartParCheckJob(pPostInfo); } else { info("Nothing to par-check for %s", pPostInfo->GetInfoName()); pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psSkipped); pPostInfo->SetWorking(false); pPostInfo->SetStage(PostInfo::ptQueued); } return; } #endif NZBParameter* pUnpackParameter = pPostInfo->GetNZBInfo()->GetParameters()->Find("*Unpack:", false); bool bUnpackParam = !(pUnpackParameter && !strcasecmp(pUnpackParameter->GetValue(), "no")); bool bUnpack = bUnpackParam && (pPostInfo->GetNZBInfo()->GetUnpackStatus() == NZBInfo::usNone); bool bParFailed = pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psFailure || pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psRepairPossible || pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psManual; bool bCleanup = !bUnpack && pPostInfo->GetNZBInfo()->GetCleanupStatus() == NZBInfo::csNone && (pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psSuccess || (pPostInfo->GetNZBInfo()->GetUnpackStatus() == NZBInfo::usSuccess && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure)) && strlen(g_pOptions->GetExtCleanupDisk()) > 0; bool bMoveInter = !bUnpack && pPostInfo->GetNZBInfo()->GetMoveStatus() == NZBInfo::msNone && pPostInfo->GetNZBInfo()->GetUnpackStatus() != NZBInfo::usFailure && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psManual && strlen(g_pOptions->GetInterDir()) > 0 && !strncmp(pPostInfo->GetNZBInfo()->GetDestDir(), g_pOptions->GetInterDir(), strlen(g_pOptions->GetInterDir())); // TODO: check if download has pp-scripts defined bool bPostScript = true; if (bUnpack && bParFailed) { warn("Skipping unpack due to %s for %s", pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psManual ? "required par-repair" : "par-failure", pPostInfo->GetInfoName()); pPostInfo->GetNZBInfo()->SetUnpackStatus(NZBInfo::usSkipped); bUnpack = false; } if (!bUnpack && !bMoveInter && !bPostScript) { pPostInfo->SetStage(PostInfo::ptFinished); return; } pPostInfo->SetProgressLabel(bUnpack ? "Unpacking" : bMoveInter ? "Moving" : "Executing post-process-script"); pPostInfo->SetWorking(true); pPostInfo->SetStage(bUnpack ? PostInfo::ptUnpacking : bMoveInter ? PostInfo::ptMoving : PostInfo::ptExecutingScript); pPostInfo->SetFileProgress(0); pPostInfo->SetStageProgress(0); SaveQueue(pDownloadQueue); if (!pPostInfo->GetStartTime()) { pPostInfo->SetStartTime(time(NULL)); } pPostInfo->SetStageTime(time(NULL)); if (bUnpack) { UpdatePauseState(g_pOptions->GetUnpackPauseQueue(), "unpack"); UnpackController::StartJob(pPostInfo); } else if (bCleanup) { UpdatePauseState(g_pOptions->GetUnpackPauseQueue() || g_pOptions->GetScriptPauseQueue(), "cleanup"); CleanupController::StartJob(pPostInfo); } else if (bMoveInter) { UpdatePauseState(g_pOptions->GetUnpackPauseQueue() || g_pOptions->GetScriptPauseQueue(), "move"); MoveController::StartJob(pPostInfo); } else { UpdatePauseState(g_pOptions->GetScriptPauseQueue(), "post-process-script"); PostScriptController::StartJob(pPostInfo); } }
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 QueueScriptCoordinator::EnqueueScript(NZBInfo* pNZBInfo, EEvent eEvent) { if (!m_bHasQueueScripts) { return; } m_mutexQueue.Lock(); if (eEvent == qeNzbDownloaded) { // delete all other queued scripts for this nzb for (Queue::iterator it = m_Queue.begin(); it != m_Queue.end(); ) { QueueItem* pQueueItem = *it; if (pQueueItem->GetNZBID() == pNZBInfo->GetID()) { delete pQueueItem; it = m_Queue.erase(it); continue; } it++; } } // respect option "EventInterval" time_t tCurTime = time(NULL); if (eEvent == qeFileDownloaded && (g_pOptions->GetEventInterval() == -1 || (g_pOptions->GetEventInterval() > 0 && tCurTime - pNZBInfo->GetQueueScriptTime() > 0 && (int)(tCurTime - pNZBInfo->GetQueueScriptTime()) < g_pOptions->GetEventInterval()))) { m_mutexQueue.Unlock(); return; } for (ScriptConfig::Scripts::iterator it = g_pScriptConfig->GetScripts()->begin(); it != g_pScriptConfig->GetScripts()->end(); it++) { ScriptConfig::Script* pScript = *it; if (!pScript->GetQueueScript()) { continue; } bool bUseScript = false; // check queue-scripts const char* szQueueScript = g_pOptions->GetQueueScript(); if (!Util::EmptyStr(szQueueScript)) { // split szQueueScript into tokens Tokenizer tok(szQueueScript, ",;"); while (const char* szScriptName = tok.Next()) { if (Util::SameFilename(szScriptName, pScript->GetName())) { bUseScript = true; break; } } } // check post-processing-scripts if (!bUseScript) { for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++) { NZBParameter* pParameter = *it; const char* szVarname = pParameter->GetName(); if (strlen(szVarname) > 0 && szVarname[0] != '*' && szVarname[strlen(szVarname)-1] == ':' && (!strcasecmp(pParameter->GetValue(), "yes") || !strcasecmp(pParameter->GetValue(), "on") || !strcasecmp(pParameter->GetValue(), "1"))) { char szScriptName[1024]; strncpy(szScriptName, szVarname, 1024); szScriptName[1024-1] = '\0'; szScriptName[strlen(szScriptName)-1] = '\0'; // remove trailing ':' if (Util::SameFilename(szScriptName, pScript->GetName())) { bUseScript = true; break; } } } } bUseScript &= Util::EmptyStr(pScript->GetQueueEvents()) || strstr(pScript->GetQueueEvents(), QUEUE_EVENT_NAMES[eEvent]); if (bUseScript) { bool bAlreadyQueued = false; if (eEvent == qeFileDownloaded) { // check if this script is already queued for this nzb for (Queue::iterator it2 = m_Queue.begin(); it2 != m_Queue.end(); it2++) { QueueItem* pQueueItem = *it2; if (pQueueItem->GetNZBID() == pNZBInfo->GetID() && pQueueItem->GetScript() == pScript) { bAlreadyQueued = true; break; } } } if (!bAlreadyQueued) { QueueItem* pQueueItem = new QueueItem(pNZBInfo->GetID(), pScript, eEvent); if (m_pCurItem) { m_Queue.push_back(pQueueItem); } else { StartScript(pNZBInfo, pQueueItem); } } pNZBInfo->SetQueueScriptTime(time(NULL)); } } m_mutexQueue.Unlock(); }