mirror of
https://github.com/nzbget/nzbget.git
synced 2025-12-24 06:37:44 -05:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d9d43a542 |
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
@@ -136,9 +136,6 @@ void ArticleDownloader::Run()
|
||||
debug("Entering ArticleDownloader-loop");
|
||||
|
||||
SetStatus(adRunning);
|
||||
|
||||
BuildOutputFilename();
|
||||
|
||||
m_szResultFilename = m_pArticleInfo->GetResultFilename();
|
||||
|
||||
if (g_pOptions->GetContinuePartial())
|
||||
@@ -369,7 +366,7 @@ ArticleDownloader::EStatus ArticleDownloader::Download()
|
||||
for (int retry = 3; retry > 0; retry--)
|
||||
{
|
||||
szResponse = m_pConnection->Request(tmp);
|
||||
if ((szResponse && !strncmp(szResponse, "2", 1)) || m_pConnection->GetAuthError())
|
||||
if (szResponse && !strncmp(szResponse, "2", 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -591,8 +588,7 @@ bool ArticleDownloader::PrepareFile(char* szLine)
|
||||
if (g_pOptions->GetDupeCheck())
|
||||
{
|
||||
m_pFileInfo->LockOutputFile();
|
||||
bool bOutputInitialized = m_pFileInfo->GetOutputInitialized();
|
||||
if (!bOutputInitialized)
|
||||
if (!m_pFileInfo->GetOutputInitialized())
|
||||
{
|
||||
char* pb = strstr(szLine, " name=");
|
||||
if (pb)
|
||||
@@ -606,6 +602,11 @@ bool ArticleDownloader::PrepareFile(char* szLine)
|
||||
strncpy(m_szArticleFilename, pb, pe - pb);
|
||||
m_szArticleFilename[pe - pb] = '\0';
|
||||
}
|
||||
if (m_pFileInfo->IsDupe(m_szArticleFilename))
|
||||
{
|
||||
m_bDuplicate = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!g_pOptions->GetDirectWrite())
|
||||
@@ -613,11 +614,6 @@ bool ArticleDownloader::PrepareFile(char* szLine)
|
||||
m_pFileInfo->SetOutputInitialized(true);
|
||||
}
|
||||
m_pFileInfo->UnlockOutputFile();
|
||||
if (!bOutputInitialized && m_szArticleFilename && m_pFileInfo->IsDupe(m_szArticleFilename))
|
||||
{
|
||||
m_bDuplicate = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pOptions->GetDirectWrite())
|
||||
@@ -632,7 +628,6 @@ bool ArticleDownloader::PrepareFile(char* szLine)
|
||||
long iArticleFilesize = atol(pb);
|
||||
if (!CreateOutputFile(iArticleFilesize))
|
||||
{
|
||||
m_pFileInfo->UnlockOutputFile();
|
||||
return false;
|
||||
}
|
||||
m_pFileInfo->SetOutputInitialized(true);
|
||||
@@ -694,58 +689,22 @@ bool ArticleDownloader::CreateOutputFile(int iSize)
|
||||
if (iMaxlen > 1024-1) iMaxlen = 1024-1;
|
||||
strncpy(szDestDir, m_szOutputFilename, iMaxlen);
|
||||
szDestDir[iMaxlen] = '\0';
|
||||
char szErrBuf[1024];
|
||||
|
||||
if (!Util::ForceDirectories(szDestDir, szErrBuf, sizeof(szErrBuf)))
|
||||
if (!Util::ForceDirectories(szDestDir))
|
||||
{
|
||||
error("Could not create directory %s: %s", szDestDir, szErrBuf);
|
||||
error("Could not create directory %s! Errcode: %i", szDestDir, errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Util::CreateSparseFile(m_szOutputFilename, iSize))
|
||||
{
|
||||
error("Could not create file %s", m_szOutputFilename);
|
||||
error("Could not create file %s!", m_szOutputFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArticleDownloader::BuildOutputFilename()
|
||||
{
|
||||
char szFilename[1024];
|
||||
|
||||
snprintf(szFilename, 1024, "%s%i.%03i", g_pOptions->GetTempDir(), m_pFileInfo->GetID(), m_pArticleInfo->GetPartNumber());
|
||||
szFilename[1024-1] = '\0';
|
||||
m_pArticleInfo->SetResultFilename(szFilename);
|
||||
|
||||
char tmpname[1024];
|
||||
snprintf(tmpname, 1024, "%s.tmp", szFilename);
|
||||
tmpname[1024-1] = '\0';
|
||||
SetTempFilename(tmpname);
|
||||
|
||||
if (g_pOptions->GetDirectWrite())
|
||||
{
|
||||
m_pFileInfo->LockOutputFile();
|
||||
|
||||
if (m_pFileInfo->GetOutputFilename())
|
||||
{
|
||||
strncpy(szFilename, m_pFileInfo->GetOutputFilename(), 1024);
|
||||
szFilename[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szFilename, 1024, "%s%c%i.out.tmp", m_pFileInfo->GetNZBInfo()->GetDestDir(), (int)PATH_SEPARATOR, m_pFileInfo->GetID());
|
||||
szFilename[1024-1] = '\0';
|
||||
m_pFileInfo->SetOutputFilename(szFilename);
|
||||
}
|
||||
|
||||
m_pFileInfo->UnlockOutputFile();
|
||||
|
||||
SetOutputFilename(szFilename);
|
||||
}
|
||||
}
|
||||
|
||||
ArticleDownloader::EStatus ArticleDownloader::DecodeCheck()
|
||||
{
|
||||
bool bDirectWrite = g_pOptions->GetDirectWrite() && m_eFormat == Decoder::efYenc;
|
||||
@@ -767,7 +726,7 @@ ArticleDownloader::EStatus ArticleDownloader::DecodeCheck()
|
||||
else
|
||||
{
|
||||
warn("Decoding %s failed: no binary data or unsupported encoding format", m_szInfoName);
|
||||
return adFailed;
|
||||
return adFatalError;
|
||||
}
|
||||
|
||||
Decoder::EStatus eStatus = pDecoder->Check();
|
||||
@@ -945,10 +904,9 @@ void ArticleDownloader::CompleteFileParts()
|
||||
}
|
||||
|
||||
// Ensure the DstDir is created
|
||||
char szErrBuf[1024];
|
||||
if (!Util::ForceDirectories(szNZBDestDir, szErrBuf, sizeof(szErrBuf)))
|
||||
if (!Util::ForceDirectories(szNZBDestDir))
|
||||
{
|
||||
error("Could not create directory %s: %s", szNZBDestDir, szErrBuf);
|
||||
error("Could not create directory %s! Errcode: %i", szNZBDestDir, errno);
|
||||
SetStatus(adJoined);
|
||||
return;
|
||||
}
|
||||
@@ -1115,6 +1073,27 @@ void ArticleDownloader::CompleteFileParts()
|
||||
{
|
||||
warn("%i of %i article downloads failed for \"%s\"", iBrokenCount, m_pFileInfo->GetArticles()->size(), InfoFilename);
|
||||
|
||||
if (g_pOptions->GetRenameBroken())
|
||||
{
|
||||
char brokenfn[1024];
|
||||
snprintf(brokenfn, 1024, "%s_broken", ofn);
|
||||
brokenfn[1024-1] = '\0';
|
||||
if (Util::MoveFile(ofn, brokenfn))
|
||||
{
|
||||
detail("Renaming broken file from %s to %s", ofn, brokenfn);
|
||||
}
|
||||
else
|
||||
{
|
||||
warn("Renaming broken file from %s to %s failed", ofn, brokenfn);
|
||||
}
|
||||
strncpy(ofn, brokenfn, 1024);
|
||||
ofn[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
detail("Not renaming broken file %s", ofn);
|
||||
}
|
||||
|
||||
if (g_pOptions->GetCreateBrokenLog())
|
||||
{
|
||||
char szBrokenLogName[1024];
|
||||
@@ -1147,10 +1126,9 @@ bool ArticleDownloader::MoveCompletedFiles(NZBInfo* pNZBInfo, const char* szOldD
|
||||
}
|
||||
|
||||
// Ensure the DstDir is created
|
||||
char szErrBuf[1024];
|
||||
if (!Util::ForceDirectories(pNZBInfo->GetDestDir(), szErrBuf, sizeof(szErrBuf)))
|
||||
if (!Util::ForceDirectories(pNZBInfo->GetDestDir()))
|
||||
{
|
||||
error("Could not create directory %s: %s", pNZBInfo->GetDestDir(), szErrBuf);
|
||||
error("Could not create directory %s! Errcode: %i", pNZBInfo->GetDestDir(), errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,14 +77,10 @@ private:
|
||||
bool Write(char* szLine, int iLen);
|
||||
bool PrepareFile(char* szLine);
|
||||
bool CreateOutputFile(int iSize);
|
||||
void BuildOutputFilename();
|
||||
EStatus DecodeCheck();
|
||||
void FreeConnection(bool bKeepConnected);
|
||||
EStatus CheckResponse(const char* szResponse, const char* szComment);
|
||||
void SetStatus(EStatus eStatus) { m_eStatus = eStatus; }
|
||||
const char* GetTempFilename() { return m_szTempFilename; }
|
||||
void SetTempFilename(const char* v);
|
||||
void SetOutputFilename(const char* v);
|
||||
|
||||
public:
|
||||
ArticleDownloader();
|
||||
@@ -99,6 +95,9 @@ public:
|
||||
bool Terminate();
|
||||
time_t GetLastUpdateTime() { return m_tLastUpdateTime; }
|
||||
void SetLastUpdateTimeNow() { m_tLastUpdateTime = ::time(NULL); }
|
||||
const char* GetTempFilename() { return m_szTempFilename; }
|
||||
void SetTempFilename(const char* v);
|
||||
void SetOutputFilename(const char* v);
|
||||
const char* GetArticleFilename() { return m_szArticleFilename; }
|
||||
void SetInfoName(const char* v);
|
||||
const char* GetInfoName() { return m_szInfoName; }
|
||||
|
||||
67
BinRpc.cpp
67
BinRpc.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,7 +34,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -52,13 +53,11 @@
|
||||
#include "PrePostProcessor.h"
|
||||
#include "Util.h"
|
||||
#include "DownloadInfo.h"
|
||||
#include "Scanner.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
extern QueueCoordinator* g_pQueueCoordinator;
|
||||
extern UrlCoordinator* g_pUrlCoordinator;
|
||||
extern PrePostProcessor* g_pPrePostProcessor;
|
||||
extern Scanner* g_pScanner;
|
||||
extern void ExitProc();
|
||||
extern void Reload();
|
||||
|
||||
@@ -104,10 +103,9 @@ void BinRpcProcessor::Execute()
|
||||
return;
|
||||
}
|
||||
|
||||
if ((strlen(g_pOptions->GetControlUsername()) > 0 && strcmp(m_MessageBase.m_szUsername, g_pOptions->GetControlUsername())) ||
|
||||
strcmp(m_MessageBase.m_szPassword, g_pOptions->GetControlPassword()))
|
||||
if (strcmp(m_MessageBase.m_szPassword, g_pOptions->GetControlPassword()))
|
||||
{
|
||||
warn("nzbget request received on port %i from %s, but username or password invalid", g_pOptions->GetControlPort(), m_pConnection->GetRemoteAddr());
|
||||
warn("nzbget request received on port %i from %s, but password invalid", g_pOptions->GetControlPort(), m_pConnection->GetRemoteAddr());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -343,10 +341,9 @@ void DownloadBinCommand::Execute()
|
||||
return;
|
||||
}
|
||||
|
||||
int iBufLen = ntohl(DownloadRequest.m_iTrailingDataLength);
|
||||
char* pRecvBuffer = (char*)malloc(iBufLen);
|
||||
char* pRecvBuffer = (char*)malloc(ntohl(DownloadRequest.m_iTrailingDataLength) + 1);
|
||||
|
||||
if (!m_pConnection->Recv(pRecvBuffer, iBufLen))
|
||||
if (!m_pConnection->Recv(pRecvBuffer, ntohl(DownloadRequest.m_iTrailingDataLength)))
|
||||
{
|
||||
error("invalid request");
|
||||
free(pRecvBuffer);
|
||||
@@ -355,17 +352,35 @@ void DownloadBinCommand::Execute()
|
||||
|
||||
int iPriority = ntohl(DownloadRequest.m_iPriority);
|
||||
bool bAddPaused = ntohl(DownloadRequest.m_bAddPaused);
|
||||
bool bAddTop = ntohl(DownloadRequest.m_bAddFirst);
|
||||
|
||||
bool bOK = g_pScanner->AddExternalFile(DownloadRequest.m_szFilename, DownloadRequest.m_szCategory,
|
||||
iPriority, NULL, bAddTop, bAddPaused, NULL, pRecvBuffer, iBufLen, true);
|
||||
|
||||
char tmp[1024];
|
||||
snprintf(tmp, 1024, bOK ? "Collection %s added to queue" : "Download Request failed for %s",
|
||||
Util::BaseFileName(DownloadRequest.m_szFilename));
|
||||
tmp[1024-1] = '\0';
|
||||
|
||||
SendBoolResponse(bOK, tmp);
|
||||
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromBuffer(DownloadRequest.m_szFilename, DownloadRequest.m_szCategory, pRecvBuffer, ntohl(DownloadRequest.m_iTrailingDataLength));
|
||||
|
||||
if (pNZBFile)
|
||||
{
|
||||
info("Request: Queue collection %s", DownloadRequest.m_szFilename);
|
||||
|
||||
for (NZBFile::FileInfos::iterator it = pNZBFile->GetFileInfos()->begin(); it != pNZBFile->GetFileInfos()->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
pFileInfo->SetPriority(iPriority);
|
||||
pFileInfo->SetPaused(bAddPaused);
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, ntohl(DownloadRequest.m_bAddFirst));
|
||||
delete pNZBFile;
|
||||
|
||||
char tmp[1024];
|
||||
snprintf(tmp, 1024, "Collection %s added to queue", Util::BaseFileName(DownloadRequest.m_szFilename));
|
||||
tmp[1024-1] = '\0';
|
||||
SendBoolResponse(true, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp[1024];
|
||||
snprintf(tmp, 1024, "Download Request failed for %s", Util::BaseFileName(DownloadRequest.m_szFilename));
|
||||
tmp[1024-1] = '\0';
|
||||
SendBoolResponse(false, tmp);
|
||||
}
|
||||
|
||||
free(pRecvBuffer);
|
||||
}
|
||||
@@ -782,7 +797,7 @@ void EditQueueBinCommand::Execute()
|
||||
}
|
||||
else
|
||||
{
|
||||
bOK = g_pPrePostProcessor->QueueEditList(&cIDList, (PrePostProcessor::EEditAction)iAction, iOffset, szText);
|
||||
bOK = g_pPrePostProcessor->QueueEditList(&cIDList, (PrePostProcessor::EEditAction)iAction, iOffset);
|
||||
}
|
||||
|
||||
free(pBuf);
|
||||
@@ -832,6 +847,7 @@ void PostQueueBinCommand::Execute()
|
||||
{
|
||||
PostInfo* pPostInfo = *it;
|
||||
bufsize += strlen(pPostInfo->GetNZBInfo()->GetFilename()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetParFilename()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetInfoName()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetNZBInfo()->GetDestDir()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetProgressLabel()) + 1;
|
||||
@@ -854,12 +870,15 @@ void PostQueueBinCommand::Execute()
|
||||
pPostQueueAnswer->m_iTotalTimeSec = htonl((int)(pPostInfo->GetStartTime() ? tCurTime - pPostInfo->GetStartTime() : 0));
|
||||
pPostQueueAnswer->m_iStageTimeSec = htonl((int)(pPostInfo->GetStageTime() ? tCurTime - pPostInfo->GetStageTime() : 0));
|
||||
pPostQueueAnswer->m_iNZBFilenameLen = htonl(strlen(pPostInfo->GetNZBInfo()->GetFilename()) + 1);
|
||||
pPostQueueAnswer->m_iParFilename = htonl(strlen(pPostInfo->GetParFilename()) + 1);
|
||||
pPostQueueAnswer->m_iInfoNameLen = htonl(strlen(pPostInfo->GetInfoName()) + 1);
|
||||
pPostQueueAnswer->m_iDestDirLen = htonl(strlen(pPostInfo->GetNZBInfo()->GetDestDir()) + 1);
|
||||
pPostQueueAnswer->m_iProgressLabelLen = htonl(strlen(pPostInfo->GetProgressLabel()) + 1);
|
||||
bufptr += sizeof(SNZBPostQueueResponseEntry);
|
||||
strcpy(bufptr, pPostInfo->GetNZBInfo()->GetFilename());
|
||||
bufptr += ntohl(pPostQueueAnswer->m_iNZBFilenameLen);
|
||||
strcpy(bufptr, pPostInfo->GetParFilename());
|
||||
bufptr += ntohl(pPostQueueAnswer->m_iParFilename);
|
||||
strcpy(bufptr, pPostInfo->GetInfoName());
|
||||
bufptr += ntohl(pPostQueueAnswer->m_iInfoNameLen);
|
||||
strcpy(bufptr, pPostInfo->GetNZBInfo()->GetDestDir());
|
||||
@@ -945,7 +964,7 @@ void ScanBinCommand::Execute()
|
||||
|
||||
bool bSyncMode = ntohl(ScanRequest.m_bSyncMode);
|
||||
|
||||
g_pScanner->ScanNZBDir(bSyncMode);
|
||||
g_pPrePostProcessor->ScanNZBDir(bSyncMode);
|
||||
SendBoolResponse(true, bSyncMode ? "Scan-Command completed" : "Scan-Command scheduled successfully");
|
||||
}
|
||||
|
||||
@@ -1007,7 +1026,7 @@ void HistoryBinCommand::Execute()
|
||||
pListAnswer->m_iSizeHi = htonl(iSizeHi);
|
||||
pListAnswer->m_iFileCount = htonl(pNZBInfo->GetFileCount());
|
||||
pListAnswer->m_iParStatus = htonl(pNZBInfo->GetParStatus());
|
||||
pListAnswer->m_iScriptStatus = htonl(pNZBInfo->GetScriptStatuses()->CalcTotalStatus());
|
||||
pListAnswer->m_iScriptStatus = htonl(pNZBInfo->GetScriptStatus());
|
||||
}
|
||||
else if (pHistoryInfo->GetKind() == HistoryInfo::hkUrlInfo)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
nzbget-11.0:
|
||||
- please see subversion log at
|
||||
http://sourceforge.net/p/nzbget/code/log
|
||||
|
||||
nzbget-10.2:
|
||||
- fixed potential segfault which could happen with file paths longer
|
||||
than 1024 characters;
|
||||
|
||||
381
Connection.cpp
381
Connection.cpp
@@ -37,7 +37,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
@@ -219,7 +219,7 @@ bool Connection::Connect()
|
||||
}
|
||||
else
|
||||
{
|
||||
DoDisconnect();
|
||||
Connection::DoDisconnect();
|
||||
}
|
||||
|
||||
return bRes;
|
||||
@@ -243,120 +243,35 @@ bool Connection::Disconnect()
|
||||
return bRes;
|
||||
}
|
||||
|
||||
bool Connection::Bind()
|
||||
int Connection::Bind()
|
||||
{
|
||||
debug("Binding");
|
||||
|
||||
if (m_eStatus == csListening)
|
||||
{
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo addr_hints, *addr_list, *addr;
|
||||
char iPortStr[sizeof(int) * 4 + 1]; // is enough to hold any converted int
|
||||
|
||||
memset(&addr_hints, 0, sizeof(addr_hints));
|
||||
addr_hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
|
||||
addr_hints.ai_socktype = SOCK_STREAM,
|
||||
addr_hints.ai_flags = AI_PASSIVE; // For wildcard IP address
|
||||
|
||||
sprintf(iPortStr, "%d", m_iPort);
|
||||
|
||||
int res = getaddrinfo(m_szHost, iPortStr, &addr_hints, &addr_list);
|
||||
if (res != 0)
|
||||
{
|
||||
error("Could not resolve hostname %s", m_szHost);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
for (addr = addr_list; addr != NULL; addr = addr->ai_next)
|
||||
{
|
||||
m_iSocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if (m_iSocket != INVALID_SOCKET)
|
||||
{
|
||||
int opt = 1;
|
||||
setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
|
||||
res = bind(m_iSocket, addr->ai_addr, addr->ai_addrlen);
|
||||
if (res != -1)
|
||||
{
|
||||
// Connection established
|
||||
break;
|
||||
}
|
||||
// Connection failed
|
||||
closesocket(m_iSocket);
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(addr_list);
|
||||
|
||||
#else
|
||||
|
||||
struct sockaddr_in sSocketAddress;
|
||||
memset(&sSocketAddress, 0, sizeof(sSocketAddress));
|
||||
sSocketAddress.sin_family = AF_INET;
|
||||
if (!m_szHost || strlen(m_szHost) == 0)
|
||||
{
|
||||
sSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
sSocketAddress.sin_addr.s_addr = ResolveHostAddr(m_szHost);
|
||||
if (sSocketAddress.sin_addr.s_addr == (unsigned int)-1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sSocketAddress.sin_port = htons(m_iPort);
|
||||
|
||||
m_iSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Socket creation failed for %s", m_szHost, true, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
|
||||
|
||||
int res = bind(m_iSocket, (struct sockaddr *) &sSocketAddress, sizeof(sSocketAddress));
|
||||
if (res == -1)
|
||||
{
|
||||
// Connection failed
|
||||
closesocket(m_iSocket);
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Binding socket failed for %s", m_szHost, true, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listen(m_iSocket, 100) < 0)
|
||||
{
|
||||
ReportError("Listen on socket failed for %s", m_szHost, true, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_eStatus = csListening;
|
||||
int iRes = DoBind();
|
||||
|
||||
return true;
|
||||
if (iRes == 0)
|
||||
{
|
||||
m_eStatus = csListening;
|
||||
}
|
||||
|
||||
return iRes;
|
||||
}
|
||||
|
||||
int Connection::WriteLine(const char* pBuffer)
|
||||
{
|
||||
//debug("Connection::WriteLine");
|
||||
//debug("Connection::write(char* line)");
|
||||
|
||||
if (m_eStatus != csConnected)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int iRes = send(m_iSocket, pBuffer, strlen(pBuffer), 0);
|
||||
int iRes = DoWriteLine(pBuffer);
|
||||
|
||||
return iRes;
|
||||
}
|
||||
@@ -391,73 +306,9 @@ char* Connection::ReadLine(char* pBuffer, int iSize, int* pBytesRead)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* pBufPtr = pBuffer;
|
||||
iSize--; // for trailing '0'
|
||||
int iBytesRead = 0;
|
||||
int iBufAvail = m_iBufAvail; // local variable is faster
|
||||
char* szBufPtr = m_szBufPtr; // local variable is faster
|
||||
while (iSize)
|
||||
{
|
||||
if (!iBufAvail)
|
||||
{
|
||||
iBufAvail = recv(m_iSocket, m_szReadBuf, CONNECTION_READBUFFER_SIZE, 0);
|
||||
if (iBufAvail < 0)
|
||||
{
|
||||
ReportError("Could not receive data on socket", NULL, true, 0);
|
||||
break;
|
||||
}
|
||||
else if (iBufAvail == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
szBufPtr = m_szReadBuf;
|
||||
m_szReadBuf[iBufAvail] = '\0';
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
char* p = (char*)memchr(szBufPtr, '\n', iBufAvail);
|
||||
if (p)
|
||||
{
|
||||
len = (int)(p - szBufPtr + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = iBufAvail;
|
||||
}
|
||||
|
||||
if (len > iSize)
|
||||
{
|
||||
len = iSize;
|
||||
}
|
||||
|
||||
memcpy(pBufPtr, szBufPtr, len);
|
||||
pBufPtr += len;
|
||||
szBufPtr += len;
|
||||
iBufAvail -= len;
|
||||
iBytesRead += len;
|
||||
iSize -= len;
|
||||
|
||||
if (p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pBufPtr = '\0';
|
||||
|
||||
m_iBufAvail = iBufAvail > 0 ? iBufAvail : 0; // copy back to member
|
||||
m_szBufPtr = szBufPtr; // copy back to member
|
||||
|
||||
if (pBytesRead)
|
||||
{
|
||||
*pBytesRead = iBytesRead;
|
||||
}
|
||||
|
||||
if (pBufPtr == pBuffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pBuffer;
|
||||
char* res = DoReadLine(pBuffer, iSize, pBytesRead);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Connection* Connection::Accept()
|
||||
@@ -469,17 +320,13 @@ Connection* Connection::Accept()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SOCKET iSocket = accept(m_iSocket, NULL, NULL);
|
||||
if (iSocket == INVALID_SOCKET && m_eStatus != csCancelled)
|
||||
{
|
||||
ReportError("Could not accept connection", NULL, true, 0);
|
||||
}
|
||||
if (iSocket == INVALID_SOCKET)
|
||||
SOCKET iRes = DoAccept();
|
||||
if (iRes == INVALID_SOCKET)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Connection* pCon = new Connection(iSocket, m_bTLS);
|
||||
Connection* pCon = new Connection(iRes, m_bTLS);
|
||||
|
||||
return pCon;
|
||||
}
|
||||
@@ -661,12 +508,200 @@ bool Connection::DoDisconnect()
|
||||
return true;
|
||||
}
|
||||
|
||||
int Connection::DoWriteLine(const char* pBuffer)
|
||||
{
|
||||
//debug("Connection::doWrite()");
|
||||
return send(m_iSocket, pBuffer, strlen(pBuffer), 0);
|
||||
}
|
||||
|
||||
char* Connection::DoReadLine(char* pBuffer, int iSize, int* pBytesRead)
|
||||
{
|
||||
//debug( "Connection::DoReadLine()" );
|
||||
char* pBufPtr = pBuffer;
|
||||
iSize--; // for trailing '0'
|
||||
int iBytesRead = 0;
|
||||
int iBufAvail = m_iBufAvail; // local variable is faster
|
||||
char* szBufPtr = m_szBufPtr; // local variable is faster
|
||||
while (iSize)
|
||||
{
|
||||
if (!iBufAvail)
|
||||
{
|
||||
iBufAvail = recv(m_iSocket, m_szReadBuf, CONNECTION_READBUFFER_SIZE, 0);
|
||||
if (iBufAvail < 0)
|
||||
{
|
||||
ReportError("Could not receive data on socket", NULL, true, 0);
|
||||
break;
|
||||
}
|
||||
else if (iBufAvail == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
szBufPtr = m_szReadBuf;
|
||||
m_szReadBuf[iBufAvail] = '\0';
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
char* p = (char*)memchr(szBufPtr, '\n', iBufAvail);
|
||||
if (p)
|
||||
{
|
||||
len = (int)(p - szBufPtr + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = iBufAvail;
|
||||
}
|
||||
|
||||
if (len > iSize)
|
||||
{
|
||||
len = iSize;
|
||||
}
|
||||
|
||||
memcpy(pBufPtr, szBufPtr, len);
|
||||
pBufPtr += len;
|
||||
szBufPtr += len;
|
||||
iBufAvail -= len;
|
||||
iBytesRead += len;
|
||||
iSize -= len;
|
||||
|
||||
if (p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pBufPtr = '\0';
|
||||
|
||||
m_iBufAvail = iBufAvail > 0 ? iBufAvail : 0; // copy back to member
|
||||
m_szBufPtr = szBufPtr; // copy back to member
|
||||
|
||||
if (pBytesRead)
|
||||
{
|
||||
*pBytesRead = iBytesRead;
|
||||
}
|
||||
|
||||
if (pBufPtr == pBuffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
|
||||
void Connection::ReadBuffer(char** pBuffer, int *iBufLen)
|
||||
{
|
||||
*iBufLen = m_iBufAvail;
|
||||
*pBuffer = m_szBufPtr;
|
||||
m_iBufAvail = 0;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
int Connection::DoBind()
|
||||
{
|
||||
debug("Do binding");
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo addr_hints, *addr_list, *addr;
|
||||
char iPortStr[sizeof(int) * 4 + 1]; // is enough to hold any converted int
|
||||
|
||||
memset(&addr_hints, 0, sizeof(addr_hints));
|
||||
addr_hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
|
||||
addr_hints.ai_socktype = SOCK_STREAM,
|
||||
addr_hints.ai_flags = AI_PASSIVE; // For wildcard IP address
|
||||
|
||||
sprintf(iPortStr, "%d", m_iPort);
|
||||
|
||||
int res = getaddrinfo(m_szHost, iPortStr, &addr_hints, &addr_list);
|
||||
if (res != 0)
|
||||
{
|
||||
error("Could not resolve hostname %s", m_szHost);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
for (addr = addr_list; addr != NULL; addr = addr->ai_next)
|
||||
{
|
||||
m_iSocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if (m_iSocket != INVALID_SOCKET)
|
||||
{
|
||||
int opt = 1;
|
||||
setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
|
||||
res = bind(m_iSocket, addr->ai_addr, addr->ai_addrlen);
|
||||
if (res != -1)
|
||||
{
|
||||
// Connection established
|
||||
break;
|
||||
}
|
||||
// Connection failed
|
||||
closesocket(m_iSocket);
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(addr_list);
|
||||
|
||||
#else
|
||||
|
||||
struct sockaddr_in sSocketAddress;
|
||||
memset(&sSocketAddress, 0, sizeof(sSocketAddress));
|
||||
sSocketAddress.sin_family = AF_INET;
|
||||
if (!m_szHost || strlen(m_szHost) == 0)
|
||||
{
|
||||
sSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
sSocketAddress.sin_addr.s_addr = ResolveHostAddr(m_szHost);
|
||||
if (sSocketAddress.sin_addr.s_addr == (unsigned int)-1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sSocketAddress.sin_port = htons(m_iPort);
|
||||
|
||||
m_iSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Socket creation failed for %s", m_szHost, true, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
|
||||
|
||||
int res = bind(m_iSocket, (struct sockaddr *) &sSocketAddress, sizeof(sSocketAddress));
|
||||
if (res == -1)
|
||||
{
|
||||
// Connection failed
|
||||
closesocket(m_iSocket);
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Binding socket failed for %s", m_szHost, true, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(m_iSocket, 100) < 0)
|
||||
{
|
||||
ReportError("Listen on socket failed for %s", m_szHost, true, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SOCKET Connection::DoAccept()
|
||||
{
|
||||
SOCKET iSocket = accept(m_iSocket, NULL, NULL);
|
||||
|
||||
if (iSocket == INVALID_SOCKET && m_eStatus != csCancelled)
|
||||
{
|
||||
ReportError("Could not accept connection", NULL, true, 0);
|
||||
}
|
||||
|
||||
return iSocket;
|
||||
}
|
||||
|
||||
void Connection::Cancel()
|
||||
{
|
||||
|
||||
14
Connection.h
14
Connection.h
@@ -72,8 +72,12 @@ protected:
|
||||
|
||||
Connection(SOCKET iSocket, bool bTLS);
|
||||
void ReportError(const char* szMsgPrefix, const char* szMsgArg, bool PrintErrCode, int herrno);
|
||||
bool DoConnect();
|
||||
bool DoDisconnect();
|
||||
virtual bool DoConnect();
|
||||
virtual bool DoDisconnect();
|
||||
int DoBind();
|
||||
int DoWriteLine(const char* pBuffer);
|
||||
char* DoReadLine(char* pBuffer, int iSize, int* pBytesRead);
|
||||
SOCKET DoAccept();
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
unsigned int ResolveHostAddr(const char* szHost);
|
||||
#endif
|
||||
@@ -88,9 +92,9 @@ public:
|
||||
virtual ~Connection();
|
||||
static void Init();
|
||||
static void Final();
|
||||
virtual bool Connect();
|
||||
virtual bool Disconnect();
|
||||
bool Bind();
|
||||
bool Connect();
|
||||
bool Disconnect();
|
||||
int Bind();
|
||||
bool Send(const char* pBuffer, int iSize);
|
||||
bool Recv(char* pBuffer, int iSize);
|
||||
int TryRecv(char* pBuffer, int iSize);
|
||||
|
||||
256
DiskState.cpp
256
DiskState.cpp
@@ -77,12 +77,12 @@ bool DiskState::SaveDownloadQueue(DownloadQueue* pDownloadQueue)
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
error("Error saving diskstate: Could not create file %s", fileName);
|
||||
error("Could not create file %s", fileName);
|
||||
perror(fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(outfile, "%s%i\n", FORMATVERSION_SIGNATURE, 25);
|
||||
fprintf(outfile, "%s%i\n", FORMATVERSION_SIGNATURE, 21);
|
||||
|
||||
// save nzb-infos
|
||||
SaveNZBList(pDownloadQueue, outfile);
|
||||
@@ -129,14 +129,14 @@ bool DiskState::LoadDownloadQueue(DownloadQueue* pDownloadQueue)
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
error("Error reading diskstate: could not open file %s", fileName);
|
||||
error("Could not open file %s", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
char FileSignatur[128];
|
||||
fgets(FileSignatur, sizeof(FileSignatur), infile);
|
||||
int iFormatVersion = ParseFormatVersion(FileSignatur);
|
||||
if (iFormatVersion < 3 || iFormatVersion > 25)
|
||||
if (iFormatVersion < 3 || iFormatVersion > 21)
|
||||
{
|
||||
error("Could not load diskstate due to file version mismatch");
|
||||
fclose(infile);
|
||||
@@ -198,14 +198,13 @@ void DiskState::SaveNZBList(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetID());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetFilename());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetDestDir());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetQueuedFilename());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetName());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetCategory());
|
||||
fprintf(outfile, "%i\n", (int)pNZBInfo->GetPostProcess());
|
||||
fprintf(outfile, "%i,%i,%i,%i\n", (int)pNZBInfo->GetParStatus(), (int)pNZBInfo->GetUnpackStatus(), (int)pNZBInfo->GetMoveStatus(), (int)pNZBInfo->GetRenameStatus());
|
||||
fprintf(outfile, "%i,%i,%i,%i,%i\n", (int)pNZBInfo->GetParStatus(), (int)pNZBInfo->GetUnpackStatus(), (int)pNZBInfo->GetScriptStatus(), (int)pNZBInfo->GetMoveStatus(), (int)pNZBInfo->GetRenameStatus());
|
||||
fprintf(outfile, "%i\n", (int)pNZBInfo->GetUnpackCleanedUpDisk());
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetFileCount());
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetParkedFileCount());
|
||||
@@ -240,13 +239,6 @@ void DiskState::SaveNZBList(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
fprintf(outfile, "%s=%s\n", pParameter->GetName(), pParameter->GetValue());
|
||||
}
|
||||
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetScriptStatuses()->size());
|
||||
for (ScriptStatusList::iterator it = pNZBInfo->GetScriptStatuses()->begin(); it != pNZBInfo->GetScriptStatuses()->end(); it++)
|
||||
{
|
||||
ScriptStatus* pScriptStatus = *it;
|
||||
fprintf(outfile, "%i,%s\n", pScriptStatus->GetStatus(), pScriptStatus->GetName());
|
||||
}
|
||||
|
||||
NZBInfo::Messages* pMessages = pNZBInfo->LockMessages();
|
||||
fprintf(outfile, "%i\n", pMessages->size());
|
||||
for (NZBInfo::Messages::iterator it = pMessages->begin(); it != pMessages->end(); it++)
|
||||
@@ -273,13 +265,6 @@ bool DiskState::LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
pNZBInfo->AddReference();
|
||||
pDownloadQueue->GetNZBInfoList()->Add(pNZBInfo);
|
||||
|
||||
if (iFormatVersion >= 24)
|
||||
{
|
||||
int iID;
|
||||
if (fscanf(infile, "%i\n", &iID) != 1) goto error;
|
||||
pNZBInfo->SetID(iID);
|
||||
}
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
pNZBInfo->SetFilename(buf);
|
||||
@@ -327,18 +312,13 @@ bool DiskState::LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
{
|
||||
int iScriptStatus;
|
||||
if (fscanf(infile, "%i\n", &iScriptStatus) != 1) goto error;
|
||||
if (iScriptStatus > 1) iScriptStatus--;
|
||||
pNZBInfo->GetScriptStatuses()->Add("SCRIPT", (ScriptStatus::EStatus)iScriptStatus);
|
||||
pNZBInfo->SetScriptStatus((NZBInfo::EScriptStatus)iScriptStatus);
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 18)
|
||||
{
|
||||
int iParStatus, iUnpackStatus, iScriptStatus, iMoveStatus = 0, iRenameStatus = 0;
|
||||
if (iFormatVersion >= 23)
|
||||
{
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &iParStatus, &iUnpackStatus, &iMoveStatus, &iRenameStatus) != 4) goto error;
|
||||
}
|
||||
else if (iFormatVersion >= 21)
|
||||
if (iFormatVersion >= 21)
|
||||
{
|
||||
if (fscanf(infile, "%i,%i,%i,%i,%i\n", &iParStatus, &iUnpackStatus, &iScriptStatus, &iMoveStatus, &iRenameStatus) != 5) goto error;
|
||||
}
|
||||
@@ -352,13 +332,9 @@ bool DiskState::LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
}
|
||||
pNZBInfo->SetParStatus((NZBInfo::EParStatus)iParStatus);
|
||||
pNZBInfo->SetUnpackStatus((NZBInfo::EUnpackStatus)iUnpackStatus);
|
||||
pNZBInfo->SetScriptStatus((NZBInfo::EScriptStatus)iScriptStatus);
|
||||
pNZBInfo->SetMoveStatus((NZBInfo::EMoveStatus)iMoveStatus);
|
||||
pNZBInfo->SetRenameStatus((NZBInfo::ERenameStatus)iRenameStatus);
|
||||
if (iFormatVersion < 23)
|
||||
{
|
||||
if (iScriptStatus > 1) iScriptStatus--;
|
||||
pNZBInfo->GetScriptStatuses()->Add("SCRIPT", (ScriptStatus::EStatus)iScriptStatus);
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 19)
|
||||
@@ -423,26 +399,6 @@ bool DiskState::LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 23)
|
||||
{
|
||||
int iScriptCount;
|
||||
if (fscanf(infile, "%i\n", &iScriptCount) != 1) goto error;
|
||||
for (int i = 0; i < iScriptCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
|
||||
char* szScriptName = strchr(buf, ',');
|
||||
if (szScriptName)
|
||||
{
|
||||
szScriptName++;
|
||||
int iStatus = atoi(buf);
|
||||
if (iStatus > 1 && iFormatVersion < 25) iStatus--;
|
||||
pNZBInfo->GetScriptStatuses()->Add(szScriptName, (ScriptStatus::EStatus)iStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 11)
|
||||
{
|
||||
int iLogCount;
|
||||
@@ -534,6 +490,7 @@ bool DiskState::LoadFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQue
|
||||
}
|
||||
else
|
||||
{
|
||||
warn("Could not load diskstate for file %s", fileName);
|
||||
delete pFileInfo;
|
||||
}
|
||||
}
|
||||
@@ -561,7 +518,7 @@ bool DiskState::SaveFileInfo(FileInfo* pFileInfo, const char* szFilename)
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
error("Error saving diskstate: could not create file %s", szFilename);
|
||||
error("Could not create file %s", szFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -606,7 +563,7 @@ bool DiskState::LoadFileInfo(FileInfo* pFileInfo, const char * szFilename, bool
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
error("Error reading diskstate: could not open file %s", szFilename);
|
||||
error("Could not open file %s", szFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -675,8 +632,10 @@ void DiskState::SavePostQueue(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
{
|
||||
PostInfo* pPostInfo = *it;
|
||||
int iNZBIndex = FindNZBInfoIndex(pDownloadQueue, pPostInfo->GetNZBInfo());
|
||||
fprintf(outfile, "%i,%i\n", iNZBIndex, (int)pPostInfo->GetStage());
|
||||
fprintf(outfile, "%i,%i,%i,%i\n", iNZBIndex,
|
||||
(int)pPostInfo->GetParStatus(), (int)pPostInfo->GetUnpackStatus(), (int)pPostInfo->GetStage());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetInfoName());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetParFilename());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,18 +652,18 @@ bool DiskState::LoadPostQueue(DownloadQueue* pDownloadQueue, FILE* infile, int i
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
PostInfo* pPostInfo = NULL;
|
||||
unsigned int iNZBIndex, iStage, iDummy;
|
||||
unsigned int iNZBIndex, iParCheck, iParStatus = 0, iUnpackStatus = 0, iStage;
|
||||
if (iFormatVersion < 19)
|
||||
{
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &iNZBIndex, &iDummy, &iDummy, &iStage) != 4) goto error;
|
||||
}
|
||||
else if (iFormatVersion < 22)
|
||||
{
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &iNZBIndex, &iDummy, &iDummy, &iStage) != 4) goto error;
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &iNZBIndex, &iParCheck, &iParStatus, &iStage) != 4) goto error;
|
||||
if (!iParCheck)
|
||||
{
|
||||
iParStatus = PostInfo::psSkipped;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fscanf(infile, "%i,%i\n", &iNZBIndex, &iStage) != 2) goto error;
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &iNZBIndex, &iParStatus, &iUnpackStatus, &iStage) != 4) goto error;
|
||||
}
|
||||
if (iFormatVersion < 18 && iStage > (int)PostInfo::ptVerifyingRepaired) iStage++;
|
||||
if (iFormatVersion < 21 && iStage > (int)PostInfo::ptVerifyingRepaired) iStage++;
|
||||
@@ -714,6 +673,8 @@ bool DiskState::LoadPostQueue(DownloadQueue* pDownloadQueue, FILE* infile, int i
|
||||
{
|
||||
pPostInfo = new PostInfo();
|
||||
pPostInfo->SetNZBInfo(pDownloadQueue->GetNZBInfoList()->at(iNZBIndex - 1));
|
||||
pPostInfo->SetParStatus((PostInfo::EParStatus)iParStatus);
|
||||
pPostInfo->SetUnpackStatus((PostInfo::EUnpackStatus)iUnpackStatus);
|
||||
pPostInfo->SetStage((PostInfo::EStage)iStage);
|
||||
}
|
||||
|
||||
@@ -721,11 +682,9 @@ bool DiskState::LoadPostQueue(DownloadQueue* pDownloadQueue, FILE* infile, int i
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
if (!bSkipPostQueue) pPostInfo->SetInfoName(buf);
|
||||
|
||||
if (iFormatVersion < 22)
|
||||
{
|
||||
// ParFilename, ignore
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
}
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
if (!bSkipPostQueue) pPostInfo->SetParFilename(buf);
|
||||
|
||||
if (!bSkipPostQueue)
|
||||
{
|
||||
@@ -761,7 +720,7 @@ bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
error("Error reading diskstate: could not open file %s", fileName);
|
||||
error("Could not open file %s", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -818,8 +777,9 @@ bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
pNZBInfo->SetDestDir(buf);
|
||||
}
|
||||
|
||||
// ParFilename, ignore
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
pPostInfo->SetParFilename(buf);
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
@@ -863,7 +823,7 @@ bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
if (fscanf(infile, "%i\n", &iParCheck) != 1) goto error; // ParCheck
|
||||
|
||||
if (fscanf(infile, "%i\n", &iIntValue) != 1) goto error;
|
||||
pNZBInfo->SetParStatus(iParCheck ? (NZBInfo::EParStatus)iIntValue : NZBInfo::psSkipped);
|
||||
pPostInfo->SetParStatus(iParCheck ? (PostInfo::EParStatus)iIntValue : PostInfo::psSkipped);
|
||||
|
||||
if (iFormatVersion < 7)
|
||||
{
|
||||
@@ -954,7 +914,6 @@ error:
|
||||
|
||||
void DiskState::SaveUrlInfo(UrlInfo* pUrlInfo, FILE* outfile)
|
||||
{
|
||||
fprintf(outfile, "%i\n", pUrlInfo->GetID());
|
||||
fprintf(outfile, "%i,%i\n", (int)pUrlInfo->GetStatus(), pUrlInfo->GetPriority());
|
||||
fprintf(outfile, "%i,%i\n", (int)pUrlInfo->GetAddTop(), pUrlInfo->GetAddPaused());
|
||||
fprintf(outfile, "%s\n", pUrlInfo->GetURL());
|
||||
@@ -966,13 +925,6 @@ bool DiskState::LoadUrlInfo(UrlInfo* pUrlInfo, FILE* infile, int iFormatVersion)
|
||||
{
|
||||
char buf[10240];
|
||||
|
||||
if (iFormatVersion >= 24)
|
||||
{
|
||||
int iID;
|
||||
if (fscanf(infile, "%i\n", &iID) != 1) goto error;
|
||||
pUrlInfo->SetID(iID);
|
||||
}
|
||||
|
||||
int iStatus, iPriority;
|
||||
if (fscanf(infile, "%i,%i\n", &iStatus, &iPriority) != 2) goto error;
|
||||
if (pUrlInfo) pUrlInfo->SetStatus((UrlInfo::EStatus)iStatus);
|
||||
@@ -1013,7 +965,6 @@ void DiskState::SaveHistory(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
{
|
||||
HistoryInfo* pHistoryInfo = *it;
|
||||
|
||||
fprintf(outfile, "%i\n", pHistoryInfo->GetID());
|
||||
fprintf(outfile, "%i\n", (int)pHistoryInfo->GetKind());
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkNZBInfo)
|
||||
@@ -1039,13 +990,6 @@ bool DiskState::LoadHistory(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
HistoryInfo* pHistoryInfo = NULL;
|
||||
int iID = 0;
|
||||
|
||||
if (iFormatVersion >= 24)
|
||||
{
|
||||
if (fscanf(infile, "%i\n", &iID) != 1) goto error;
|
||||
}
|
||||
|
||||
HistoryInfo::EKind eKind = HistoryInfo::hkNZBInfo;
|
||||
|
||||
if (iFormatVersion >= 15)
|
||||
@@ -1069,11 +1013,6 @@ bool DiskState::LoadHistory(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
pHistoryInfo = new HistoryInfo(pUrlInfo);
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 24)
|
||||
{
|
||||
pHistoryInfo->SetID(iID);
|
||||
}
|
||||
|
||||
int iTime;
|
||||
if (fscanf(infile, "%i\n", &iTime) != 1) goto error;
|
||||
pHistoryInfo->SetTime((time_t)iTime);
|
||||
@@ -1104,37 +1043,136 @@ int DiskState::FindNZBInfoIndex(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes whole download queue including history.
|
||||
* Delete all files from Queue.
|
||||
* Returns true if successful, false if not
|
||||
*/
|
||||
void DiskState::DiscardDownloadQueue()
|
||||
bool DiskState::DiscardDownloadQueue()
|
||||
{
|
||||
debug("Discarding queue");
|
||||
|
||||
char szFullFilename[1024];
|
||||
snprintf(szFullFilename, 1024, "%s%s", g_pOptions->GetQueueDir(), "queue");
|
||||
szFullFilename[1024-1] = '\0';
|
||||
remove(szFullFilename);
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "queue");
|
||||
fileName[1024-1] = '\0';
|
||||
|
||||
DirBrowser dir(g_pOptions->GetQueueDir());
|
||||
while (const char* filename = dir.Next())
|
||||
FILE* infile = fopen(fileName, "rb");
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
// delete all files whose names have only characters '0'..'9'
|
||||
bool bOnlyNums = true;
|
||||
for (const char* p = filename; *p != '\0'; p++)
|
||||
error("Could not open file %s", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
char FileSignatur[128];
|
||||
fgets(FileSignatur, sizeof(FileSignatur), infile);
|
||||
int iFormatVersion = ParseFormatVersion(FileSignatur);
|
||||
if (3 <= iFormatVersion && iFormatVersion <= 21)
|
||||
{
|
||||
// skip nzb-infos
|
||||
int size = 0;
|
||||
char buf[1024];
|
||||
fscanf(infile, "%i\n", &size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (!('0' <= *p && *p <= '9'))
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // filename
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // destdir
|
||||
if (iFormatVersion >= 5)
|
||||
{
|
||||
bOnlyNums = false;
|
||||
break;
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // localfile
|
||||
}
|
||||
if (iFormatVersion >= 13)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // name
|
||||
}
|
||||
if (iFormatVersion >= 4)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // category
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // postprocess
|
||||
}
|
||||
if (iFormatVersion >= 8 && iFormatVersion < 18)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // ParStatus
|
||||
}
|
||||
if (iFormatVersion >= 9 && iFormatVersion < 18)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // ScriptStatus
|
||||
}
|
||||
if (iFormatVersion >= 18)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // ParStatus, UnpackStatus, ScriptStatus
|
||||
}
|
||||
if (iFormatVersion >= 19)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // UnpackCleanedUpDisk
|
||||
}
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // file count
|
||||
if (iFormatVersion >= 10)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // parked file count
|
||||
}
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // file size
|
||||
if (iFormatVersion >= 4)
|
||||
{
|
||||
// completed files
|
||||
int iFileCount;
|
||||
if (fscanf(infile, "%i\n", &iFileCount) != 1) break;
|
||||
for (int i = 0; i < iFileCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // filename
|
||||
}
|
||||
}
|
||||
if (iFormatVersion >= 6)
|
||||
{
|
||||
// postprocess-parameters
|
||||
int iParameterCount;
|
||||
if (fscanf(infile, "%i\n", &iParameterCount) != 1) break;
|
||||
for (int i = 0; i < iParameterCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 11)
|
||||
{
|
||||
// log-messages
|
||||
int iLogCount;
|
||||
if (fscanf(infile, "%i\n", &iLogCount) != 1) break;
|
||||
for (int i = 0; i < iLogCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bOnlyNums)
|
||||
|
||||
// file-infos
|
||||
fscanf(infile, "%i\n", &size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
snprintf(szFullFilename, 1024, "%s%s", g_pOptions->GetQueueDir(), filename);
|
||||
szFullFilename[1024-1] = '\0';
|
||||
remove(szFullFilename);
|
||||
int id;
|
||||
char tr[100];
|
||||
if (fscanf(infile, "%i,%s\n", &id, &tr) == 2)
|
||||
{
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%i", g_pOptions->GetQueueDir(), id);
|
||||
fileName[1024-1] = '\0';
|
||||
remove(fileName);
|
||||
}
|
||||
}
|
||||
res = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not discard diskstate due to file version mismatch");
|
||||
res = false;
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
if (res)
|
||||
{
|
||||
remove(fileName);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DiskState::DownloadQueueExists()
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
bool LoadDownloadQueue(DownloadQueue* pDownloadQueue);
|
||||
bool SaveFile(FileInfo* pFileInfo);
|
||||
bool LoadArticles(FileInfo* pFileInfo);
|
||||
void DiscardDownloadQueue();
|
||||
bool DiscardDownloadQueue();
|
||||
bool DiscardFile(FileInfo* pFileInfo);
|
||||
void CleanupTempDir(DownloadQueue* pDownloadQueue);
|
||||
};
|
||||
|
||||
132
DownloadInfo.cpp
132
DownloadInfo.cpp
@@ -34,10 +34,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "DownloadInfo.h"
|
||||
@@ -117,59 +117,6 @@ void NZBParameterList::SetParameter(const char* szName, const char* szValue)
|
||||
}
|
||||
|
||||
|
||||
ScriptStatus::ScriptStatus(const char* szName, EStatus eStatus)
|
||||
{
|
||||
m_szName = strdup(szName);
|
||||
m_eStatus = eStatus;
|
||||
}
|
||||
|
||||
ScriptStatus::~ScriptStatus()
|
||||
{
|
||||
if (m_szName)
|
||||
{
|
||||
free(m_szName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScriptStatusList::~ScriptStatusList()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void ScriptStatusList::Clear()
|
||||
{
|
||||
for (iterator it = begin(); it != end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
void ScriptStatusList::Add(const char* szScriptName, ScriptStatus::EStatus eStatus)
|
||||
{
|
||||
push_back(new ScriptStatus(szScriptName, eStatus));
|
||||
}
|
||||
|
||||
ScriptStatus::EStatus ScriptStatusList::CalcTotalStatus()
|
||||
{
|
||||
ScriptStatus::EStatus eStatus = ScriptStatus::srNone;
|
||||
|
||||
for (iterator it = begin(); it != end(); it++)
|
||||
{
|
||||
ScriptStatus* pScriptStatus = *it;
|
||||
// Failure-Status overrides Success-Status
|
||||
if ((pScriptStatus->GetStatus() == ScriptStatus::srSuccess && eStatus == ScriptStatus::srNone) ||
|
||||
(pScriptStatus->GetStatus() == ScriptStatus::srFailure))
|
||||
{
|
||||
eStatus = pScriptStatus->GetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
return eStatus;
|
||||
}
|
||||
|
||||
|
||||
NZBInfo::NZBInfo()
|
||||
{
|
||||
debug("Creating NZBInfo");
|
||||
@@ -186,8 +133,8 @@ NZBInfo::NZBInfo()
|
||||
m_eRenameStatus = rsNone;
|
||||
m_eParStatus = psNone;
|
||||
m_eUnpackStatus = usNone;
|
||||
m_eCleanupStatus = csNone;
|
||||
m_eMoveStatus = msNone;
|
||||
m_eScriptStatus = srNone;
|
||||
m_bDeleted = false;
|
||||
m_bParCleanup = false;
|
||||
m_bCleanupDisk = false;
|
||||
@@ -259,15 +206,6 @@ void NZBInfo::Release()
|
||||
}
|
||||
}
|
||||
|
||||
void NZBInfo::SetID(int iID)
|
||||
{
|
||||
m_iID = iID;
|
||||
if (m_iIDGen < m_iID)
|
||||
{
|
||||
m_iIDGen = m_iID;
|
||||
}
|
||||
}
|
||||
|
||||
void NZBInfo::ClearCompletedFiles()
|
||||
{
|
||||
for (Files::iterator it = m_completedFiles.begin(); it != m_completedFiles.end(); it++)
|
||||
@@ -399,9 +337,12 @@ void NZBInfo::BuildFinalDirName(char* szFinalDirBuf, int iBufSize)
|
||||
strncpy(szFinalDirBuf, szBuffer, iBufSize);
|
||||
}
|
||||
|
||||
snprintf(szBuffer, 1024, "%s%s", szFinalDirBuf, GetName());
|
||||
szBuffer[1024-1] = '\0';
|
||||
strncpy(szFinalDirBuf, szBuffer, iBufSize);
|
||||
if (g_pOptions->GetAppendNZBDir())
|
||||
{
|
||||
snprintf(szBuffer, 1024, "%s%s", szFinalDirBuf, GetName());
|
||||
szBuffer[1024-1] = '\0';
|
||||
strncpy(szFinalDirBuf, szBuffer, iBufSize);
|
||||
}
|
||||
}
|
||||
|
||||
void NZBInfo::SetParameter(const char* szName, const char* szValue)
|
||||
@@ -519,7 +460,6 @@ FileInfo::FileInfo()
|
||||
m_szSubject = NULL;
|
||||
m_szFilename = NULL;
|
||||
m_szOutputFilename = NULL;
|
||||
m_pMutexOutputFile = NULL;
|
||||
m_bFilenameConfirmed = false;
|
||||
m_lSize = 0;
|
||||
m_lRemainingSize = 0;
|
||||
@@ -532,7 +472,6 @@ FileInfo::FileInfo()
|
||||
m_iPriority = 0;
|
||||
m_bExtraPriority = false;
|
||||
m_iActiveDownloads = 0;
|
||||
m_bAutoDeleted = false;
|
||||
m_iIDGen++;
|
||||
m_iID = m_iIDGen;
|
||||
}
|
||||
@@ -553,10 +492,6 @@ FileInfo::~ FileInfo()
|
||||
{
|
||||
free(m_szOutputFilename);
|
||||
}
|
||||
if (m_pMutexOutputFile)
|
||||
{
|
||||
delete m_pMutexOutputFile;
|
||||
}
|
||||
|
||||
for (Groups::iterator it = m_Groups.begin(); it != m_Groups.end() ;it++)
|
||||
{
|
||||
@@ -581,9 +516,9 @@ void FileInfo::ClearArticles()
|
||||
m_Articles.clear();
|
||||
}
|
||||
|
||||
void FileInfo::SetID(int iID)
|
||||
void FileInfo::SetID(int s)
|
||||
{
|
||||
m_iID = iID;
|
||||
m_iID = s;
|
||||
if (m_iIDGen < m_iID)
|
||||
{
|
||||
m_iIDGen = m_iID;
|
||||
@@ -621,12 +556,12 @@ void FileInfo::MakeValidFilename()
|
||||
|
||||
void FileInfo::LockOutputFile()
|
||||
{
|
||||
m_pMutexOutputFile->Lock();
|
||||
m_mutexOutputFile.Lock();
|
||||
}
|
||||
|
||||
void FileInfo::UnlockOutputFile()
|
||||
{
|
||||
m_pMutexOutputFile->Unlock();
|
||||
m_mutexOutputFile.Unlock();
|
||||
}
|
||||
|
||||
void FileInfo::SetOutputFilename(const char* szOutputFilename)
|
||||
@@ -638,21 +573,6 @@ void FileInfo::SetOutputFilename(const char* szOutputFilename)
|
||||
m_szOutputFilename = strdup(szOutputFilename);
|
||||
}
|
||||
|
||||
void FileInfo::SetActiveDownloads(int iActiveDownloads)
|
||||
{
|
||||
m_iActiveDownloads = iActiveDownloads;
|
||||
|
||||
if (m_iActiveDownloads > 0 && !m_pMutexOutputFile)
|
||||
{
|
||||
m_pMutexOutputFile = new Mutex();
|
||||
}
|
||||
else if (m_iActiveDownloads == 0 && m_pMutexOutputFile)
|
||||
{
|
||||
delete m_pMutexOutputFile;
|
||||
m_pMutexOutputFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileInfo::IsDupe(const char* szFilename)
|
||||
{
|
||||
char fileName[1024];
|
||||
@@ -701,11 +621,16 @@ PostInfo::PostInfo()
|
||||
debug("Creating PostInfo");
|
||||
|
||||
m_pNZBInfo = NULL;
|
||||
m_szParFilename = NULL;
|
||||
m_szInfoName = NULL;
|
||||
m_bWorking = false;
|
||||
m_bDeleted = false;
|
||||
m_bRequestParCheck = false;
|
||||
m_eRenameStatus = rsNone;
|
||||
m_eParStatus = psNone;
|
||||
m_eUnpackStatus = usNone;
|
||||
m_eRequestParCheck = rpNone;
|
||||
m_bRequestParRename = false;
|
||||
m_eScriptStatus = srNone;
|
||||
m_szProgressLabel = strdup("");
|
||||
m_iFileProgress = 0;
|
||||
m_iStageProgress = 0;
|
||||
@@ -723,6 +648,10 @@ PostInfo::~ PostInfo()
|
||||
{
|
||||
debug("Destroying PostInfo");
|
||||
|
||||
if (m_szParFilename)
|
||||
{
|
||||
free(m_szParFilename);
|
||||
}
|
||||
if (m_szInfoName)
|
||||
{
|
||||
free(m_szInfoName);
|
||||
@@ -754,6 +683,11 @@ void PostInfo::SetNZBInfo(NZBInfo* pNZBInfo)
|
||||
m_pNZBInfo->AddReference();
|
||||
}
|
||||
|
||||
void PostInfo::SetParFilename(const char* szParFilename)
|
||||
{
|
||||
m_szParFilename = strdup(szParFilename);
|
||||
}
|
||||
|
||||
void PostInfo::SetInfoName(const char* szInfoName)
|
||||
{
|
||||
m_szInfoName = strdup(szInfoName);
|
||||
@@ -903,9 +837,9 @@ void UrlInfo::SetURL(const char* szURL)
|
||||
m_szURL = strdup(szURL);
|
||||
}
|
||||
|
||||
void UrlInfo::SetID(int iID)
|
||||
void UrlInfo::SetID(int s)
|
||||
{
|
||||
m_iID = iID;
|
||||
m_iID = s;
|
||||
if (m_iIDGen < m_iID)
|
||||
{
|
||||
m_iIDGen = m_iID;
|
||||
@@ -985,9 +919,9 @@ HistoryInfo::~HistoryInfo()
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryInfo::SetID(int iID)
|
||||
void HistoryInfo::SetID(int s)
|
||||
{
|
||||
m_iID = iID;
|
||||
m_iID = s;
|
||||
if (m_iIDGen < m_iID)
|
||||
{
|
||||
m_iIDGen = m_iID;
|
||||
|
||||
130
DownloadInfo.h
130
DownloadInfo.h
@@ -92,11 +92,10 @@ private:
|
||||
int m_iCompleted;
|
||||
bool m_bOutputInitialized;
|
||||
char* m_szOutputFilename;
|
||||
Mutex* m_pMutexOutputFile;
|
||||
Mutex m_mutexOutputFile;
|
||||
int m_iPriority;
|
||||
bool m_bExtraPriority;
|
||||
int m_iActiveDownloads;
|
||||
bool m_bAutoDeleted;
|
||||
|
||||
static int m_iIDGen;
|
||||
|
||||
@@ -104,7 +103,7 @@ public:
|
||||
FileInfo();
|
||||
~FileInfo();
|
||||
int GetID() { return m_iID; }
|
||||
void SetID(int iID);
|
||||
void SetID(int s);
|
||||
NZBInfo* GetNZBInfo() { return m_pNZBInfo; }
|
||||
void SetNZBInfo(NZBInfo* pNZBInfo);
|
||||
Articles* GetArticles() { return &m_Articles; }
|
||||
@@ -141,9 +140,7 @@ public:
|
||||
bool GetExtraPriority() { return m_bExtraPriority; }
|
||||
void SetExtraPriority(bool bExtraPriority) { m_bExtraPriority = bExtraPriority; };
|
||||
int GetActiveDownloads() { return m_iActiveDownloads; }
|
||||
void SetActiveDownloads(int iActiveDownloads);
|
||||
bool GetAutoDeleted() { return m_bAutoDeleted; }
|
||||
void SetAutoDeleted(bool bAutoDeleted) { m_bAutoDeleted = bAutoDeleted; }
|
||||
void SetActiveDownloads(int iActiveDownloads) { m_iActiveDownloads = iActiveDownloads; }
|
||||
};
|
||||
|
||||
typedef std::deque<FileInfo*> FileQueue;
|
||||
@@ -212,40 +209,6 @@ public:
|
||||
void SetParameter(const char* szName, const char* szValue);
|
||||
};
|
||||
|
||||
class ScriptStatus
|
||||
{
|
||||
public:
|
||||
enum EStatus
|
||||
{
|
||||
srNone,
|
||||
srFailure,
|
||||
srSuccess
|
||||
};
|
||||
|
||||
private:
|
||||
char* m_szName;
|
||||
EStatus m_eStatus;
|
||||
|
||||
friend class ScriptStatusList;
|
||||
|
||||
public:
|
||||
ScriptStatus(const char* szName, EStatus eStatus);
|
||||
~ScriptStatus();
|
||||
const char* GetName() { return m_szName; }
|
||||
EStatus GetStatus() { return m_eStatus; }
|
||||
};
|
||||
|
||||
typedef std::deque<ScriptStatus*> ScriptStatusListBase;
|
||||
|
||||
class ScriptStatusList : public ScriptStatusListBase
|
||||
{
|
||||
public:
|
||||
~ScriptStatusList();
|
||||
void Add(const char* szScriptName, ScriptStatus::EStatus eStatus);
|
||||
void Clear();
|
||||
ScriptStatus::EStatus CalcTotalStatus();
|
||||
};
|
||||
|
||||
class NZBInfoList;
|
||||
|
||||
class NZBInfo
|
||||
@@ -265,8 +228,7 @@ public:
|
||||
psSkipped,
|
||||
psFailure,
|
||||
psSuccess,
|
||||
psRepairPossible,
|
||||
psManual
|
||||
psRepairPossible
|
||||
};
|
||||
|
||||
enum EUnpackStatus
|
||||
@@ -277,11 +239,12 @@ public:
|
||||
usSuccess
|
||||
};
|
||||
|
||||
enum ECleanupStatus
|
||||
enum EScriptStatus
|
||||
{
|
||||
csNone,
|
||||
csFailure,
|
||||
csSuccess
|
||||
srNone,
|
||||
srUnknown,
|
||||
srFailure,
|
||||
srSuccess
|
||||
};
|
||||
|
||||
enum EMoveStatus
|
||||
@@ -309,17 +272,15 @@ private:
|
||||
ERenameStatus m_eRenameStatus;
|
||||
EParStatus m_eParStatus;
|
||||
EUnpackStatus m_eUnpackStatus;
|
||||
ECleanupStatus m_eCleanupStatus;
|
||||
EScriptStatus m_eScriptStatus;
|
||||
EMoveStatus m_eMoveStatus;
|
||||
char* m_szQueuedFilename;
|
||||
bool m_bDeleted;
|
||||
bool m_bParCleanup;
|
||||
bool m_bParManual;
|
||||
bool m_bCleanupDisk;
|
||||
bool m_bUnpackCleanedUpDisk;
|
||||
NZBInfoList* m_Owner;
|
||||
NZBParameterList m_ppParameters;
|
||||
ScriptStatusList m_scriptStatuses;
|
||||
Mutex m_mutexLog;
|
||||
Messages m_Messages;
|
||||
int m_iIDMessageGen;
|
||||
@@ -334,7 +295,6 @@ public:
|
||||
void AddReference();
|
||||
void Release();
|
||||
int GetID() { return m_iID; }
|
||||
void SetID(int iID);
|
||||
const char* GetFilename() { return m_szFilename; }
|
||||
void SetFilename(const char* szFilename);
|
||||
static void MakeNiceNZBName(const char* szNZBFilename, char* szBuffer, int iSize, bool bRemoveExt);
|
||||
@@ -362,10 +322,10 @@ public:
|
||||
void SetParStatus(EParStatus eParStatus) { m_eParStatus = eParStatus; }
|
||||
EUnpackStatus GetUnpackStatus() { return m_eUnpackStatus; }
|
||||
void SetUnpackStatus(EUnpackStatus eUnpackStatus) { m_eUnpackStatus = eUnpackStatus; }
|
||||
ECleanupStatus GetCleanupStatus() { return m_eCleanupStatus; }
|
||||
void SetCleanupStatus(ECleanupStatus eCleanupStatus) { m_eCleanupStatus = eCleanupStatus; }
|
||||
EMoveStatus GetMoveStatus() { return m_eMoveStatus; }
|
||||
void SetMoveStatus(EMoveStatus eMoveStatus) { m_eMoveStatus = eMoveStatus; }
|
||||
EScriptStatus GetScriptStatus() { return m_eScriptStatus; }
|
||||
void SetScriptStatus(EScriptStatus eScriptStatus) { m_eScriptStatus = eScriptStatus; }
|
||||
const char* GetQueuedFilename() { return m_szQueuedFilename; }
|
||||
void SetQueuedFilename(const char* szQueuedFilename);
|
||||
bool GetDeleted() { return m_bDeleted; }
|
||||
@@ -378,7 +338,6 @@ public:
|
||||
void SetUnpackCleanedUpDisk(bool bUnpackCleanedUpDisk) { m_bUnpackCleanedUpDisk = bUnpackCleanedUpDisk; }
|
||||
NZBParameterList* GetParameters() { return &m_ppParameters; } // needs locking (for shared objects)
|
||||
void SetParameter(const char* szName, const char* szValue); // needs locking (for shared objects)
|
||||
ScriptStatusList* GetScriptStatuses() { return &m_scriptStatuses; } // needs locking (for shared objects)
|
||||
void AppendMessage(Message::EKind eKind, time_t tTime, const char* szText);
|
||||
Messages* LockMessages();
|
||||
void UnlockMessages();
|
||||
@@ -411,15 +370,60 @@ public:
|
||||
ptFinished
|
||||
};
|
||||
|
||||
enum ERenameStatus
|
||||
{
|
||||
rsNone,
|
||||
rsSkipped,
|
||||
rsFailure,
|
||||
rsSuccess
|
||||
};
|
||||
|
||||
enum EParStatus
|
||||
{
|
||||
psNone,
|
||||
psSkipped,
|
||||
psFailure,
|
||||
psSuccess,
|
||||
psRepairPossible
|
||||
};
|
||||
|
||||
enum ERequestParCheck
|
||||
{
|
||||
rpNone,
|
||||
rpCurrent,
|
||||
rpAll
|
||||
};
|
||||
|
||||
enum EUnpackStatus
|
||||
{
|
||||
usNone,
|
||||
usSkipped,
|
||||
usFailure,
|
||||
usSuccess
|
||||
};
|
||||
|
||||
enum EScriptStatus
|
||||
{
|
||||
srNone,
|
||||
srUnknown,
|
||||
srFailure,
|
||||
srSuccess
|
||||
};
|
||||
|
||||
typedef std::deque<Message*> Messages;
|
||||
|
||||
private:
|
||||
int m_iID;
|
||||
NZBInfo* m_pNZBInfo;
|
||||
char* m_szParFilename;
|
||||
char* m_szInfoName;
|
||||
bool m_bWorking;
|
||||
bool m_bDeleted;
|
||||
bool m_bRequestParCheck;
|
||||
ERenameStatus m_eRenameStatus;
|
||||
EParStatus m_eParStatus;
|
||||
EUnpackStatus m_eUnpackStatus;
|
||||
EScriptStatus m_eScriptStatus;
|
||||
ERequestParCheck m_eRequestParCheck;
|
||||
bool m_bRequestParRename;
|
||||
EStage m_eStage;
|
||||
char* m_szProgressLabel;
|
||||
@@ -441,6 +445,8 @@ public:
|
||||
int GetID() { return m_iID; }
|
||||
NZBInfo* GetNZBInfo() { return m_pNZBInfo; }
|
||||
void SetNZBInfo(NZBInfo* pNZBInfo);
|
||||
const char* GetParFilename() { return m_szParFilename; }
|
||||
void SetParFilename(const char* szParFilename);
|
||||
const char* GetInfoName() { return m_szInfoName; }
|
||||
void SetInfoName(const char* szInfoName);
|
||||
EStage GetStage() { return m_eStage; }
|
||||
@@ -459,10 +465,18 @@ public:
|
||||
void SetWorking(bool bWorking) { m_bWorking = bWorking; }
|
||||
bool GetDeleted() { return m_bDeleted; }
|
||||
void SetDeleted(bool bDeleted) { m_bDeleted = bDeleted; }
|
||||
bool GetRequestParCheck() { return m_bRequestParCheck; }
|
||||
void SetRequestParCheck(bool bRequestParCheck) { m_bRequestParCheck = bRequestParCheck; }
|
||||
ERenameStatus GetRenameStatus() { return m_eRenameStatus; }
|
||||
void SetRenameStatus(ERenameStatus eRenameStatus) { m_eRenameStatus = eRenameStatus; }
|
||||
EParStatus GetParStatus() { return m_eParStatus; }
|
||||
void SetParStatus(EParStatus eParStatus) { m_eParStatus = eParStatus; }
|
||||
EUnpackStatus GetUnpackStatus() { return m_eUnpackStatus; }
|
||||
void SetUnpackStatus(EUnpackStatus eUnpackStatus) { m_eUnpackStatus = eUnpackStatus; }
|
||||
ERequestParCheck GetRequestParCheck() { return m_eRequestParCheck; }
|
||||
void SetRequestParCheck(ERequestParCheck eRequestParCheck) { m_eRequestParCheck = eRequestParCheck; }
|
||||
bool GetRequestParRename() { return m_bRequestParRename; }
|
||||
void SetRequestParRename(bool bRequestParRename) { m_bRequestParRename = bRequestParRename; }
|
||||
EScriptStatus GetScriptStatus() { return m_eScriptStatus; }
|
||||
void SetScriptStatus(EScriptStatus eScriptStatus) { m_eScriptStatus = eScriptStatus; }
|
||||
void AppendMessage(Message::EKind eKind, const char* szText);
|
||||
Thread* GetPostThread() { return m_pPostThread; }
|
||||
void SetPostThread(Thread* pPostThread) { m_pPostThread = pPostThread; }
|
||||
@@ -504,7 +518,7 @@ public:
|
||||
UrlInfo();
|
||||
~UrlInfo();
|
||||
int GetID() { return m_iID; }
|
||||
void SetID(int iID);
|
||||
void SetID(int s);
|
||||
const char* GetURL() { return m_szURL; } // needs locking (for shared objects)
|
||||
void SetURL(const char* szURL); // needs locking (for shared objects)
|
||||
const char* GetNZBFilename() { return m_szNZBFilename; } // needs locking (for shared objects)
|
||||
@@ -548,7 +562,7 @@ public:
|
||||
HistoryInfo(UrlInfo* pUrlInfo);
|
||||
~HistoryInfo();
|
||||
int GetID() { return m_iID; }
|
||||
void SetID(int iID);
|
||||
void SetID(int s);
|
||||
EKind GetKind() { return m_eKind; }
|
||||
NZBInfo* GetNZBInfo() { return (NZBInfo*)m_pInfo; }
|
||||
UrlInfo* GetUrlInfo() { return (UrlInfo*)m_pInfo; }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,7 +34,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -235,10 +236,6 @@ void Frontend::InitMessageBase(SNZBRequestBase* pMessageBase, int iRequest, int
|
||||
pMessageBase->m_iSignature = htonl(NZBMESSAGE_SIGNATURE);
|
||||
pMessageBase->m_iType = htonl(iRequest);
|
||||
pMessageBase->m_iStructSize = htonl(iSize);
|
||||
|
||||
strncpy(pMessageBase->m_szUsername, g_pOptions->GetControlUsername(), NZBREQUESTPASSWORDSIZE - 1);
|
||||
pMessageBase->m_szUsername[NZBREQUESTPASSWORDSIZE - 1] = '\0';
|
||||
|
||||
strncpy(pMessageBase->m_szPassword, g_pOptions->GetControlPassword(), NZBREQUESTPASSWORDSIZE);
|
||||
pMessageBase->m_szPassword[NZBREQUESTPASSWORDSIZE - 1] = '\0';
|
||||
}
|
||||
|
||||
4
Log.cpp
4
Log.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Options.h"
|
||||
|
||||
30
Makefile.am
30
Makefile.am
@@ -37,7 +37,7 @@ nzbget_SOURCES = \
|
||||
UrlCoordinator.cpp UrlCoordinator.h Unpack.cpp Unpack.h nzbget.cpp nzbget.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.cvs nzbgetd \
|
||||
Makefile.cvs nzbgetd nzbget-postprocess.sh \
|
||||
$(patches_FILES) $(windows_FILES)
|
||||
|
||||
patches_FILES = \
|
||||
@@ -51,7 +51,7 @@ doc_FILES = \
|
||||
README ChangeLog COPYING
|
||||
|
||||
exampleconf_FILES = \
|
||||
nzbget.conf
|
||||
nzbget.conf nzbget-postprocess.conf
|
||||
|
||||
webui_FILES = \
|
||||
webui/index.html webui/index.js webui/downloads.js webui/edit.js webui/fasttable.js \
|
||||
@@ -64,18 +64,16 @@ webui_FILES = \
|
||||
webui/img/download-anim-green-2x.png webui/img/download-anim-orange-2x.png \
|
||||
webui/img/transmit-reload-2x.gif
|
||||
|
||||
ppscripts_FILES = \
|
||||
ppscripts/EMail.py ppscripts/Logger.py
|
||||
|
||||
# Install
|
||||
sbin_SCRIPTS = nzbgetd
|
||||
bin_SCRIPTS = nzbget-postprocess.sh
|
||||
dist_doc_DATA = $(doc_FILES)
|
||||
exampleconfdir = $(datadir)/nzbget
|
||||
dist_exampleconf_DATA = $(exampleconf_FILES)
|
||||
webuiconfdir = $(datadir)/nzbget/webui
|
||||
dist_webuiconf_DATA = $(exampleconf_FILES)
|
||||
webuidir = $(datadir)/nzbget
|
||||
nobase_dist_webui_DATA = $(webui_FILES)
|
||||
ppscriptsdir = $(datadir)/nzbget
|
||||
nobase_dist_ppscripts_SCRIPTS = $(ppscripts_FILES)
|
||||
|
||||
# Note about "sed":
|
||||
# We need to make some changes in installed files.
|
||||
@@ -93,15 +91,12 @@ install-exec-hook:
|
||||
sed 's?/usr/local/bin?$(bindir)?' < "$(DESTDIR)$(sbindir)/nzbgetd.temp" > "$(DESTDIR)$(sbindir)/nzbgetd"
|
||||
rm "$(DESTDIR)$(sbindir)/nzbgetd.temp"
|
||||
|
||||
# Prepare example configuration file
|
||||
# Prepare example configuration files
|
||||
install-data-hook:
|
||||
rm -f "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
cp "$(DESTDIR)$(exampleconfdir)/nzbget.conf" "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:^ConfigTemplate=:ConfigTemplate=$(exampleconfdir)/nzbget.conf:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
sed 's:configuration file (typically installed:configuration file (installed:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:/usr/local/share/nzbget/nzbget.conf):$(exampleconfdir)/nzbget.conf):' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
sed 's:^WebDir=:WebDir=$(webuidir)/webui:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:typically installed to /usr/local/share/nzbget/ppscripts:installed to $(ppscriptsdir)/ppscripts:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
sed 's:"nzbget-postprocess.sh":"nzbget-postprocess.sh" (installed into $(bindir)):' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:^WebDir=:WebDir=$(webuidir)/webui:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
rm "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
|
||||
# Install configuration files into /etc
|
||||
@@ -110,9 +105,18 @@ install-conf:
|
||||
if test ! -f "$(DESTDIR)$(sysconfdir)/nzbget.conf" ; then \
|
||||
$(mkinstalldirs) "$(DESTDIR)$(sysconfdir)" ; \
|
||||
cp "$(DESTDIR)$(exampleconfdir)/nzbget.conf" "$(DESTDIR)$(sysconfdir)/nzbget.conf" ; \
|
||||
rm -f "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" ; \
|
||||
cp "$(DESTDIR)$(sysconfdir)/nzbget.conf" "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" ; \
|
||||
sed 's:^PostProcess=:PostProcess=$(bindir)/nzbget-postprocess.sh:' < "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(sysconfdir)/nzbget.conf" ; \
|
||||
rm "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" ; \
|
||||
fi
|
||||
if test ! -f "$(DESTDIR)$(sysconfdir)/nzbget-postprocess.conf" ; then \
|
||||
$(mkinstalldirs) "$(DESTDIR)$(sysconfdir)" ; \
|
||||
cp "$(DESTDIR)$(exampleconfdir)/nzbget-postprocess.conf" "$(DESTDIR)$(sysconfdir)/nzbget-postprocess.conf" ; \
|
||||
fi
|
||||
|
||||
uninstall-conf:
|
||||
rm -f "$(DESTDIR)$(sysconfdir)/nzbget-postprocess.conf"
|
||||
rm -f "$(DESTDIR)$(sysconfdir)/nzbget.conf"
|
||||
|
||||
# Determining subversion revision:
|
||||
|
||||
139
Makefile.in
139
Makefile.in
@@ -62,7 +62,7 @@ host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
bin_PROGRAMS = nzbget$(EXEEXT)
|
||||
DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \
|
||||
$(dist_exampleconf_DATA) $(nobase_dist_ppscripts_SCRIPTS) \
|
||||
$(dist_exampleconf_DATA) $(dist_webuiconf_DATA) \
|
||||
$(nobase_dist_webui_DATA) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||
@@ -77,9 +77,10 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(ppscriptsdir)" \
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \
|
||||
"$(DESTDIR)$(sbindir)" "$(DESTDIR)$(docdir)" \
|
||||
"$(DESTDIR)$(exampleconfdir)" "$(DESTDIR)$(webuidir)"
|
||||
"$(DESTDIR)$(exampleconfdir)" "$(DESTDIR)$(webuiconfdir)" \
|
||||
"$(DESTDIR)$(webuidir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_nzbget_OBJECTS = ArticleDownloader.$(OBJEXT) BinRpc.$(OBJEXT) \
|
||||
@@ -100,15 +101,9 @@ am_nzbget_OBJECTS = ArticleDownloader.$(OBJEXT) BinRpc.$(OBJEXT) \
|
||||
nzbget.$(OBJEXT)
|
||||
nzbget_OBJECTS = $(am_nzbget_OBJECTS)
|
||||
nzbget_LDADD = $(LDADD)
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
nobase_dist_ppscriptsSCRIPT_INSTALL = $(install_sh_SCRIPT)
|
||||
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
|
||||
sbinSCRIPT_INSTALL = $(INSTALL_SCRIPT)
|
||||
SCRIPTS = $(nobase_dist_ppscripts_SCRIPTS) $(sbin_SCRIPTS)
|
||||
SCRIPTS = $(bin_SCRIPTS) $(sbin_SCRIPTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@@ -123,11 +118,18 @@ CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(nzbget_SOURCES)
|
||||
DIST_SOURCES = $(nzbget_SOURCES)
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
dist_docDATA_INSTALL = $(INSTALL_DATA)
|
||||
dist_exampleconfDATA_INSTALL = $(INSTALL_DATA)
|
||||
dist_webuiconfDATA_INSTALL = $(INSTALL_DATA)
|
||||
nobase_dist_webuiDATA_INSTALL = $(install_sh_DATA)
|
||||
DATA = $(dist_doc_DATA) $(dist_exampleconf_DATA) \
|
||||
$(nobase_dist_webui_DATA)
|
||||
$(dist_webuiconf_DATA) $(nobase_dist_webui_DATA)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
@@ -255,7 +257,7 @@ nzbget_SOURCES = \
|
||||
UrlCoordinator.cpp UrlCoordinator.h Unpack.cpp Unpack.h nzbget.cpp nzbget.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.cvs nzbgetd \
|
||||
Makefile.cvs nzbgetd nzbget-postprocess.sh \
|
||||
$(patches_FILES) $(windows_FILES)
|
||||
|
||||
patches_FILES = \
|
||||
@@ -269,7 +271,7 @@ doc_FILES = \
|
||||
README ChangeLog COPYING
|
||||
|
||||
exampleconf_FILES = \
|
||||
nzbget.conf
|
||||
nzbget.conf nzbget-postprocess.conf
|
||||
|
||||
webui_FILES = \
|
||||
webui/index.html webui/index.js webui/downloads.js webui/edit.js webui/fasttable.js \
|
||||
@@ -282,19 +284,17 @@ webui_FILES = \
|
||||
webui/img/download-anim-green-2x.png webui/img/download-anim-orange-2x.png \
|
||||
webui/img/transmit-reload-2x.gif
|
||||
|
||||
ppscripts_FILES = \
|
||||
ppscripts/EMail.py ppscripts/Logger.py
|
||||
|
||||
|
||||
# Install
|
||||
sbin_SCRIPTS = nzbgetd
|
||||
bin_SCRIPTS = nzbget-postprocess.sh
|
||||
dist_doc_DATA = $(doc_FILES)
|
||||
exampleconfdir = $(datadir)/nzbget
|
||||
dist_exampleconf_DATA = $(exampleconf_FILES)
|
||||
webuiconfdir = $(datadir)/nzbget/webui
|
||||
dist_webuiconf_DATA = $(exampleconf_FILES)
|
||||
webuidir = $(datadir)/nzbget
|
||||
nobase_dist_webui_DATA = $(webui_FILES)
|
||||
ppscriptsdir = $(datadir)/nzbget
|
||||
nobase_dist_ppscripts_SCRIPTS = $(ppscripts_FILES)
|
||||
|
||||
# Ignore "svn_version.cpp" in distcleancheck
|
||||
distcleancheck_listfiles = \
|
||||
@@ -382,30 +382,24 @@ clean-binPROGRAMS:
|
||||
nzbget$(EXEEXT): $(nzbget_OBJECTS) $(nzbget_DEPENDENCIES)
|
||||
@rm -f nzbget$(EXEEXT)
|
||||
$(CXXLINK) $(nzbget_LDFLAGS) $(nzbget_OBJECTS) $(nzbget_LDADD) $(LIBS)
|
||||
install-nobase_dist_ppscriptsSCRIPTS: $(nobase_dist_ppscripts_SCRIPTS)
|
||||
install-binSCRIPTS: $(bin_SCRIPTS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(ppscriptsdir)" || $(mkdir_p) "$(DESTDIR)$(ppscriptsdir)"
|
||||
@$(am__vpath_adj_setup) \
|
||||
list='$(nobase_dist_ppscripts_SCRIPTS)'; for p in $$list; do \
|
||||
$(am__vpath_adj) p=$$f; \
|
||||
test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_SCRIPTS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
if test -f $$d$$p; then \
|
||||
f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
|
||||
f=`echo "$$p" | sed 's|[^/]*$$||'`"$$f"; \
|
||||
echo " $(nobase_dist_ppscriptsSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(ppscriptsdir)/$$f'"; \
|
||||
$(nobase_dist_ppscriptsSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(ppscriptsdir)/$$f"; \
|
||||
echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
$(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-nobase_dist_ppscriptsSCRIPTS:
|
||||
uninstall-binSCRIPTS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@$(am__vpath_adj_setup) \
|
||||
list='$(nobase_dist_ppscripts_SCRIPTS)'; for p in $$list; do \
|
||||
$(am__vpath_adj) p=$$f; \
|
||||
@list='$(bin_SCRIPTS)'; for p in $$list; do \
|
||||
f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
|
||||
f=`echo "$$p" | sed 's|[^/]*$$||'`"$$f"; \
|
||||
echo " rm -f '$(DESTDIR)$(ppscriptsdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(ppscriptsdir)/$$f"; \
|
||||
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||
done
|
||||
install-sbinSCRIPTS: $(sbin_SCRIPTS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@@ -520,6 +514,23 @@ uninstall-dist_exampleconfDATA:
|
||||
echo " rm -f '$(DESTDIR)$(exampleconfdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(exampleconfdir)/$$f"; \
|
||||
done
|
||||
install-dist_webuiconfDATA: $(dist_webuiconf_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(webuiconfdir)" || $(mkdir_p) "$(DESTDIR)$(webuiconfdir)"
|
||||
@list='$(dist_webuiconf_DATA)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
f=$(am__strip_dir) \
|
||||
echo " $(dist_webuiconfDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(webuiconfdir)/$$f'"; \
|
||||
$(dist_webuiconfDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(webuiconfdir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-dist_webuiconfDATA:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(dist_webuiconf_DATA)'; for p in $$list; do \
|
||||
f=$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(webuiconfdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(webuiconfdir)/$$f"; \
|
||||
done
|
||||
install-nobase_dist_webuiDATA: $(nobase_dist_webui_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(webuidir)" || $(mkdir_p) "$(DESTDIR)$(webuidir)"
|
||||
@@ -591,7 +602,7 @@ distclean-tags:
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
mkdir $(distdir)
|
||||
$(mkdir_p) $(distdir)/ppscripts $(distdir)/webui $(distdir)/webui/img $(distdir)/webui/lib
|
||||
$(mkdir_p) $(distdir)/webui $(distdir)/webui/img $(distdir)/webui/lib
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
@@ -722,7 +733,7 @@ check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) config.h
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(ppscriptsdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(exampleconfdir)" "$(DESTDIR)$(webuidir)"; do \
|
||||
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(exampleconfdir)" "$(DESTDIR)$(webuiconfdir)" "$(DESTDIR)$(webuidir)"; do \
|
||||
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
@@ -771,12 +782,12 @@ info: info-am
|
||||
info-am:
|
||||
|
||||
install-data-am: install-dist_docDATA install-dist_exampleconfDATA \
|
||||
install-nobase_dist_ppscriptsSCRIPTS \
|
||||
install-nobase_dist_webuiDATA
|
||||
install-dist_webuiconfDATA install-nobase_dist_webuiDATA
|
||||
@$(NORMAL_INSTALL)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-data-hook
|
||||
|
||||
install-exec-am: install-binPROGRAMS install-sbinSCRIPTS
|
||||
install-exec-am: install-binPROGRAMS install-binSCRIPTS \
|
||||
install-sbinSCRIPTS
|
||||
@$(NORMAL_INSTALL)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
|
||||
|
||||
@@ -805,9 +816,9 @@ ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-dist_docDATA \
|
||||
uninstall-dist_exampleconfDATA uninstall-info-am \
|
||||
uninstall-nobase_dist_ppscriptsSCRIPTS \
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
|
||||
uninstall-dist_docDATA uninstall-dist_exampleconfDATA \
|
||||
uninstall-dist_webuiconfDATA uninstall-info-am \
|
||||
uninstall-nobase_dist_webuiDATA uninstall-sbinSCRIPTS
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
|
||||
@@ -816,19 +827,19 @@ uninstall-am: uninstall-binPROGRAMS uninstall-dist_docDATA \
|
||||
distclean distclean-compile distclean-generic distclean-hdr \
|
||||
distclean-tags distcleancheck distdir distuninstallcheck dvi \
|
||||
dvi-am html html-am info info-am install install-am \
|
||||
install-binPROGRAMS install-data install-data-am \
|
||||
install-data-hook install-dist_docDATA \
|
||||
install-dist_exampleconfDATA install-exec install-exec-am \
|
||||
install-exec-hook install-info install-info-am install-man \
|
||||
install-nobase_dist_ppscriptsSCRIPTS \
|
||||
install-nobase_dist_webuiDATA install-sbinSCRIPTS \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
|
||||
tags uninstall uninstall-am uninstall-binPROGRAMS \
|
||||
uninstall-dist_docDATA uninstall-dist_exampleconfDATA \
|
||||
uninstall-info-am uninstall-nobase_dist_ppscriptsSCRIPTS \
|
||||
uninstall-nobase_dist_webuiDATA uninstall-sbinSCRIPTS
|
||||
install-binPROGRAMS install-binSCRIPTS install-data \
|
||||
install-data-am install-data-hook install-dist_docDATA \
|
||||
install-dist_exampleconfDATA install-dist_webuiconfDATA \
|
||||
install-exec install-exec-am install-exec-hook install-info \
|
||||
install-info-am install-man install-nobase_dist_webuiDATA \
|
||||
install-sbinSCRIPTS install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
|
||||
ps ps-am tags uninstall uninstall-am uninstall-binPROGRAMS \
|
||||
uninstall-binSCRIPTS uninstall-dist_docDATA \
|
||||
uninstall-dist_exampleconfDATA uninstall-dist_webuiconfDATA \
|
||||
uninstall-info-am uninstall-nobase_dist_webuiDATA \
|
||||
uninstall-sbinSCRIPTS
|
||||
|
||||
|
||||
# Note about "sed":
|
||||
@@ -847,15 +858,12 @@ install-exec-hook:
|
||||
sed 's?/usr/local/bin?$(bindir)?' < "$(DESTDIR)$(sbindir)/nzbgetd.temp" > "$(DESTDIR)$(sbindir)/nzbgetd"
|
||||
rm "$(DESTDIR)$(sbindir)/nzbgetd.temp"
|
||||
|
||||
# Prepare example configuration file
|
||||
# Prepare example configuration files
|
||||
install-data-hook:
|
||||
rm -f "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
cp "$(DESTDIR)$(exampleconfdir)/nzbget.conf" "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:^ConfigTemplate=:ConfigTemplate=$(exampleconfdir)/nzbget.conf:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
sed 's:configuration file (typically installed:configuration file (installed:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:/usr/local/share/nzbget/nzbget.conf):$(exampleconfdir)/nzbget.conf):' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
sed 's:^WebDir=:WebDir=$(webuidir)/webui:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:typically installed to /usr/local/share/nzbget/ppscripts:installed to $(ppscriptsdir)/ppscripts:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
sed 's:"nzbget-postprocess.sh":"nzbget-postprocess.sh" (installed into $(bindir)):' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
sed 's:^WebDir=:WebDir=$(webuidir)/webui:' < "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(exampleconfdir)/nzbget.conf"
|
||||
rm "$(DESTDIR)$(exampleconfdir)/nzbget.conf.temp"
|
||||
|
||||
# Install configuration files into /etc
|
||||
@@ -864,9 +872,18 @@ install-conf:
|
||||
if test ! -f "$(DESTDIR)$(sysconfdir)/nzbget.conf" ; then \
|
||||
$(mkinstalldirs) "$(DESTDIR)$(sysconfdir)" ; \
|
||||
cp "$(DESTDIR)$(exampleconfdir)/nzbget.conf" "$(DESTDIR)$(sysconfdir)/nzbget.conf" ; \
|
||||
rm -f "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" ; \
|
||||
cp "$(DESTDIR)$(sysconfdir)/nzbget.conf" "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" ; \
|
||||
sed 's:^PostProcess=:PostProcess=$(bindir)/nzbget-postprocess.sh:' < "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" > "$(DESTDIR)$(sysconfdir)/nzbget.conf" ; \
|
||||
rm "$(DESTDIR)$(sysconfdir)/nzbget.conf.temp" ; \
|
||||
fi
|
||||
if test ! -f "$(DESTDIR)$(sysconfdir)/nzbget-postprocess.conf" ; then \
|
||||
$(mkinstalldirs) "$(DESTDIR)$(sysconfdir)" ; \
|
||||
cp "$(DESTDIR)$(exampleconfdir)/nzbget-postprocess.conf" "$(DESTDIR)$(sysconfdir)/nzbget-postprocess.conf" ; \
|
||||
fi
|
||||
|
||||
uninstall-conf:
|
||||
rm -f "$(DESTDIR)$(sysconfdir)/nzbget-postprocess.conf"
|
||||
rm -f "$(DESTDIR)$(sysconfdir)/nzbget.conf"
|
||||
|
||||
# Determining subversion revision:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef MESSAGEBASE_H
|
||||
#define MESSAGEBASE_H
|
||||
|
||||
static const int32_t NZBMESSAGE_SIGNATURE = 0x6E7A6217; // = "nzb-XX" (protocol version)
|
||||
static const int32_t NZBMESSAGE_SIGNATURE = 0x6E7A6212; // = "nzb-XX" (protocol version)
|
||||
static const int NZBREQUESTFILENAMESIZE = 512;
|
||||
static const int NZBREQUESTPASSWORDSIZE = 32;
|
||||
|
||||
@@ -81,7 +81,6 @@ enum eRemoteEditAction
|
||||
eRemoteEditActionFilePauseExtraPars, // pause only (almost all) pars, except main par-file (does not affect other files)
|
||||
eRemoteEditActionFileSetPriority, // set priority for files
|
||||
eRemoteEditActionFileReorder, // (not supported)
|
||||
eRemoteEditActionFileSplit, // split - create new group from selected files
|
||||
eRemoteEditActionGroupMoveOffset, // move group to m_iOffset relative to the current position in download-queue
|
||||
eRemoteEditActionGroupMoveTop, // move group to the top of download-queue
|
||||
eRemoteEditActionGroupMoveBottom, // move group to the bottom of download-queue
|
||||
@@ -101,8 +100,7 @@ enum eRemoteEditAction
|
||||
eRemoteEditActionPostDelete, // delete post-job
|
||||
eRemoteEditActionHistoryDelete, // delete history-item
|
||||
eRemoteEditActionHistoryReturn, // move history-item back to download queue
|
||||
eRemoteEditActionHistoryProcess, // move history-item back to download queue and start postprocessing
|
||||
eRemoteEditActionHistorySetParameter // set post-process parameter for history-item
|
||||
eRemoteEditActionHistoryProcess // move history-item back to download queue and start postprocessing
|
||||
};
|
||||
|
||||
// Possible values for field "m_iAction" of struct "SNZBPauseUnpauseRequest":
|
||||
@@ -128,8 +126,7 @@ struct SNZBRequestBase
|
||||
int32_t m_iSignature; // Signature must be NZBMESSAGE_SIGNATURE in integer-value
|
||||
int32_t m_iStructSize; // Size of the entire struct
|
||||
int32_t m_iType; // Message type, see enum in NZBMessageRequest-namespace
|
||||
char m_szUsername[NZBREQUESTPASSWORDSIZE]; // User name
|
||||
char m_szPassword[NZBREQUESTPASSWORDSIZE]; // Password
|
||||
char m_szPassword[NZBREQUESTPASSWORDSIZE]; // Password needs to be in every request
|
||||
};
|
||||
|
||||
// The basic SNZBResposneBase struct, used in all responses
|
||||
@@ -425,10 +422,12 @@ struct SNZBPostQueueResponseEntry
|
||||
int32_t m_iTotalTimeSec; // Number of seconds this post-job is beeing processed (after it first changed the state from QUEUED).
|
||||
int32_t m_iStageTimeSec; // Number of seconds the current stage is beeing processed.
|
||||
int32_t m_iNZBFilenameLen; // Length of NZBFileName-string (m_szNZBFilename), following to this record
|
||||
int32_t m_iParFilename; // Length of ParFilename-string (m_szParFilename), following to this record
|
||||
int32_t m_iInfoNameLen; // Length of Filename-string (m_szFilename), following to this record
|
||||
int32_t m_iDestDirLen; // Length of DestDir-string (m_szDestDir), following to this record
|
||||
int32_t m_iProgressLabelLen; // Length of ProgressLabel-string (m_szProgressLabel), following to this record
|
||||
//char m_szNZBFilename[m_iNZBFilenameLen]; // variable sized, may contain full path (local path on client) or only filename
|
||||
//char m_szParFilename[m_iParFilename]; // variable sized
|
||||
//char m_szInfoName[m_iInfoNameLen]; // variable sized
|
||||
//char m_szDestDir[m_iDestDirLen]; // variable sized
|
||||
//char m_szProgressLabel[m_iProgressLabelLen]; // variable sized
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Log.h"
|
||||
@@ -85,14 +85,17 @@ const char* NNTPConnection::Request(const char* req)
|
||||
{
|
||||
debug("%s requested authorization", GetHost());
|
||||
|
||||
//authentication required!
|
||||
if (!Authenticate())
|
||||
{
|
||||
m_bAuthError = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//try again
|
||||
WriteLine(req);
|
||||
answer = ReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
return answer;
|
||||
}
|
||||
|
||||
return answer;
|
||||
@@ -100,16 +103,13 @@ const char* NNTPConnection::Request(const char* req)
|
||||
|
||||
bool NNTPConnection::Authenticate()
|
||||
{
|
||||
if (!m_pNewsServer->GetUser() || strlen(m_pNewsServer->GetUser()) == 0 ||
|
||||
!m_pNewsServer->GetPassword() || strlen(m_pNewsServer->GetPassword()) == 0)
|
||||
if (!(m_pNewsServer)->GetUser() ||
|
||||
!(m_pNewsServer)->GetPassword())
|
||||
{
|
||||
error("Server%i (%s) requested authorization but username/password are not set in settings", m_pNewsServer->GetID(), m_pNewsServer->GetHost());
|
||||
m_bAuthError = true;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_bAuthError = !AuthInfoUser(0);
|
||||
return !m_bAuthError;
|
||||
return AuthInfoUser();
|
||||
}
|
||||
|
||||
bool NNTPConnection::AuthInfoUser(int iRecur)
|
||||
@@ -128,7 +128,7 @@ bool NNTPConnection::AuthInfoUser(int iRecur)
|
||||
char* answer = ReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
if (!answer)
|
||||
{
|
||||
ReportErrorAnswer("Authorization for server%i (%s) failed: Connection closed by remote host", NULL);
|
||||
ReportError("Authorization for %s failed: Connection closed by remote host", GetHost(), false, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ bool NNTPConnection::AuthInfoUser(int iRecur)
|
||||
|
||||
if (GetStatus() != csCancelled)
|
||||
{
|
||||
ReportErrorAnswer("Authorization for server%i (%s) failed (Answer: %s)", answer);
|
||||
ReportErrorAnswer("Authorization for %s failed (Answer: %s)", answer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ bool NNTPConnection::AuthInfoPass(int iRecur)
|
||||
char* answer = ReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
if (!answer)
|
||||
{
|
||||
ReportErrorAnswer("Authorization for server%i (%s) failed: Connection closed by remote host", NULL);
|
||||
ReportError("Authorization for %s failed: Connection closed by remote host", GetHost(), false, 0);
|
||||
return false;
|
||||
}
|
||||
else if (!strncmp(answer, "2", 1))
|
||||
@@ -188,7 +188,7 @@ bool NNTPConnection::AuthInfoPass(int iRecur)
|
||||
|
||||
if (GetStatus() != csCancelled)
|
||||
{
|
||||
ReportErrorAnswer("Authorization for server%i (%s) failed (Answer: %s)", answer);
|
||||
ReportErrorAnswer("Authorization for %s failed (Answer: %s)", answer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -207,6 +207,10 @@ const char* NNTPConnection::JoinGroup(const char* grp)
|
||||
tmp[1024-1] = '\0';
|
||||
|
||||
const char* answer = Request(tmp);
|
||||
if (m_bAuthError)
|
||||
{
|
||||
return answer;
|
||||
}
|
||||
|
||||
if (answer && !strncmp(answer, "2", 1))
|
||||
{
|
||||
@@ -226,40 +230,26 @@ const char* NNTPConnection::JoinGroup(const char* grp)
|
||||
return answer;
|
||||
}
|
||||
|
||||
bool NNTPConnection::Connect()
|
||||
bool NNTPConnection::DoConnect()
|
||||
{
|
||||
debug("Opening connection to %s", GetHost());
|
||||
|
||||
if (m_eStatus == csConnected)
|
||||
bool res = Connection::DoConnect();
|
||||
if (!res)
|
||||
{
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!Connection::Connect())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char* answer = ReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
char* answer = DoReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
|
||||
if (!answer)
|
||||
{
|
||||
ReportErrorAnswer("Connection to server%i (%s) failed: Connection closed by remote host", NULL);
|
||||
Disconnect();
|
||||
ReportError("Connection to %s failed: Connection closed by remote host", GetHost(), false, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strncmp(answer, "2", 1))
|
||||
{
|
||||
ReportErrorAnswer("Connection to server%i (%s) failed (Answer: %s)", answer);
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((m_pNewsServer->GetUser() && strlen(m_pNewsServer->GetUser()) > 0 &&
|
||||
m_pNewsServer->GetPassword() && strlen(m_pNewsServer->GetPassword()) > 0) &&
|
||||
!Authenticate())
|
||||
{
|
||||
ReportErrorAnswer("Connection to %s failed (Answer: %s)", answer);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -268,7 +258,7 @@ bool NNTPConnection::Connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NNTPConnection::Disconnect()
|
||||
bool NNTPConnection::DoDisconnect()
|
||||
{
|
||||
if (m_eStatus == csConnected)
|
||||
{
|
||||
@@ -279,13 +269,13 @@ bool NNTPConnection::Disconnect()
|
||||
m_szActiveGroup = NULL;
|
||||
}
|
||||
}
|
||||
return Connection::Disconnect();
|
||||
return Connection::DoDisconnect();
|
||||
}
|
||||
|
||||
void NNTPConnection::ReportErrorAnswer(const char* szMsgPrefix, const char* szAnswer)
|
||||
{
|
||||
char szErrStr[1024];
|
||||
snprintf(szErrStr, 1024, szMsgPrefix, m_pNewsServer->GetID(), m_pNewsServer->GetHost(), szAnswer);
|
||||
snprintf(szErrStr, 1024, szMsgPrefix, GetHost(), szAnswer);
|
||||
szErrStr[1024-1] = '\0';
|
||||
|
||||
ReportError(szErrStr, NULL, false, 0);
|
||||
|
||||
@@ -33,26 +33,26 @@
|
||||
class NNTPConnection : public Connection
|
||||
{
|
||||
private:
|
||||
NewsServer* m_pNewsServer;
|
||||
char* m_szActiveGroup;
|
||||
char* m_szLineBuf;
|
||||
bool m_bAuthError;
|
||||
NewsServer* m_pNewsServer;
|
||||
char* m_szActiveGroup;
|
||||
char* m_szLineBuf;
|
||||
bool m_bAuthError;
|
||||
|
||||
void Clear();
|
||||
void ReportErrorAnswer(const char* szMsgPrefix, const char* szAnswer);
|
||||
bool Authenticate();
|
||||
bool AuthInfoUser(int iRecur);
|
||||
bool AuthInfoPass(int iRecur);
|
||||
virtual bool DoConnect();
|
||||
virtual bool DoDisconnect();
|
||||
void Clear();
|
||||
void ReportErrorAnswer(const char* szMsgPrefix, const char* szAnswer);
|
||||
|
||||
public:
|
||||
NNTPConnection(NewsServer* pNewsServer);
|
||||
virtual ~NNTPConnection();
|
||||
virtual bool Connect();
|
||||
virtual bool Disconnect();
|
||||
NewsServer* GetNewsServer() { return m_pNewsServer; }
|
||||
const char* Request(const char* req);
|
||||
const char* JoinGroup(const char* grp);
|
||||
bool GetAuthError() { return m_bAuthError; }
|
||||
NNTPConnection(NewsServer* pNewsServer);
|
||||
virtual ~NNTPConnection();
|
||||
NewsServer* GetNewsServer() { return m_pNewsServer; }
|
||||
const char* Request(const char* req);
|
||||
bool Authenticate();
|
||||
bool AuthInfoUser(int iRecur = 0);
|
||||
bool AuthInfoPass(int iRecur = 0);
|
||||
const char* JoinGroup(const char* grp);
|
||||
bool GetAuthError() { return m_bAuthError; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
65
NZBFile.cpp
65
NZBFile.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -121,6 +121,16 @@ void NZBFile::DetachFileInfos()
|
||||
m_FileInfos.clear();
|
||||
}
|
||||
|
||||
NZBFile* NZBFile::CreateFromBuffer(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize)
|
||||
{
|
||||
return Create(szFileName, szCategory, szBuffer, iSize, true);
|
||||
}
|
||||
|
||||
NZBFile* NZBFile::CreateFromFile(const char* szFileName, const char* szCategory)
|
||||
{
|
||||
return Create(szFileName, szCategory, NULL, 0, false);
|
||||
}
|
||||
|
||||
void NZBFile::AddArticle(FileInfo* pFileInfo, ArticleInfo* pArticleInfo)
|
||||
{
|
||||
// make Article-List big enough
|
||||
@@ -347,7 +357,7 @@ void NZBFile::ProcessFilenames()
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory)
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize, bool bFromBuffer)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
|
||||
@@ -364,15 +374,21 @@ NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory)
|
||||
doc->put_resolveExternals(VARIANT_FALSE);
|
||||
doc->put_validateOnParse(VARIANT_FALSE);
|
||||
doc->put_async(VARIANT_FALSE);
|
||||
|
||||
// filename needs to be properly encoded
|
||||
char* szURL = (char*)malloc(strlen(szFileName)*3 + 1);
|
||||
EncodeURL(szFileName, szURL);
|
||||
debug("url=\"%s\"", szURL);
|
||||
_variant_t v(szURL);
|
||||
free(szURL);
|
||||
|
||||
VARIANT_BOOL success = doc->load(v);
|
||||
VARIANT_BOOL success;
|
||||
if (bFromBuffer)
|
||||
{
|
||||
success = doc->loadXML(szBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// filename needs to be properly encoded
|
||||
char* szURL = (char*)malloc(strlen(szFileName)*3 + 1);
|
||||
EncodeURL(szFileName, szURL);
|
||||
debug("url=\"%s\"", szURL);
|
||||
_variant_t v(szURL);
|
||||
free(szURL);
|
||||
success = doc->load(v);
|
||||
}
|
||||
if (success == VARIANT_FALSE)
|
||||
{
|
||||
_bstr_t r(doc->GetparseError()->reason);
|
||||
@@ -466,14 +482,11 @@ bool NZBFile::ParseNZB(IUnknown* nzb)
|
||||
int partNumber = atoi(number);
|
||||
int lsize = atoi(bytes);
|
||||
|
||||
if (partNumber > 0)
|
||||
{
|
||||
ArticleInfo* pArticle = new ArticleInfo();
|
||||
pArticle->SetPartNumber(partNumber);
|
||||
pArticle->SetMessageID(szId);
|
||||
pArticle->SetSize(lsize);
|
||||
AddArticle(pFileInfo, pArticle);
|
||||
}
|
||||
ArticleInfo* pArticle = new ArticleInfo();
|
||||
pArticle->SetPartNumber(partNumber);
|
||||
pArticle->SetMessageID(szId);
|
||||
pArticle->SetSize(lsize);
|
||||
AddArticle(pFileInfo, pArticle);
|
||||
|
||||
if (lsize > 0)
|
||||
{
|
||||
@@ -488,7 +501,7 @@ bool NZBFile::ParseNZB(IUnknown* nzb)
|
||||
|
||||
#else
|
||||
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory)
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize, bool bFromBuffer)
|
||||
{
|
||||
NZBFile* pFile = new NZBFile(szFileName, szCategory);
|
||||
|
||||
@@ -499,10 +512,18 @@ NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory)
|
||||
SAX_handler.error = reinterpret_cast<errorSAXFunc>(SAX_error);
|
||||
SAX_handler.getEntity = reinterpret_cast<getEntitySAXFunc>(SAX_getEntity);
|
||||
|
||||
int ret = 0;
|
||||
pFile->m_bIgnoreNextError = false;
|
||||
|
||||
int ret = xmlSAXUserParseFile(&SAX_handler, pFile, szFileName);
|
||||
|
||||
if (bFromBuffer)
|
||||
{
|
||||
ret = xmlSAXUserParseMemory(&SAX_handler, pFile, szBuffer, iSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xmlSAXUserParseFile(&SAX_handler, pFile, szFileName);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
pFile->ProcessFilenames();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -66,10 +66,12 @@ private:
|
||||
void Parse_EndElement(const char *name);
|
||||
void Parse_Content(const char *buf, int len);
|
||||
#endif
|
||||
static NZBFile* Create(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize, bool bFromBuffer);
|
||||
|
||||
public:
|
||||
virtual ~NZBFile();
|
||||
static NZBFile* Create(const char* szFileName, const char* szCategory);
|
||||
static NZBFile* CreateFromBuffer(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize);
|
||||
static NZBFile* CreateFromFile(const char* szFileName, const char* szCategory);
|
||||
const char* GetFileName() const { return m_szFileName; }
|
||||
FileInfos* GetFileInfos() { return &m_FileInfos; }
|
||||
NZBInfo* GetNZBInfo() { return m_pNZBInfo; }
|
||||
|
||||
671
Options.cpp
671
Options.cpp
File diff suppressed because it is too large
Load Diff
123
Options.h
123
Options.h
@@ -28,11 +28,8 @@
|
||||
#define OPTIONS_H
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Util.h"
|
||||
|
||||
class Options
|
||||
{
|
||||
@@ -80,11 +77,11 @@ public:
|
||||
omColored,
|
||||
omNCurses
|
||||
};
|
||||
enum EParCheck
|
||||
enum ELoadPars
|
||||
{
|
||||
pcAuto,
|
||||
pcForce,
|
||||
pcManual
|
||||
lpNone,
|
||||
lpOne,
|
||||
lpAll
|
||||
};
|
||||
enum EParScan
|
||||
{
|
||||
@@ -109,6 +106,12 @@ public:
|
||||
mmRegEx
|
||||
};
|
||||
|
||||
enum EDomain
|
||||
{
|
||||
dmServer = 1,
|
||||
dmPostProcess
|
||||
};
|
||||
|
||||
class OptEntry
|
||||
{
|
||||
private:
|
||||
@@ -142,31 +145,6 @@ public:
|
||||
OptEntry* FindOption(const char* szName);
|
||||
};
|
||||
|
||||
class ConfigTemplate
|
||||
{
|
||||
private:
|
||||
char* m_szName;
|
||||
char* m_szDisplayName;
|
||||
char* m_szTemplate;
|
||||
|
||||
friend class Options;
|
||||
|
||||
public:
|
||||
ConfigTemplate(const char* szName, const char* szDisplayName, const char* szTemplate);
|
||||
~ConfigTemplate();
|
||||
const char* GetName() { return m_szName; }
|
||||
const char* GetDisplayName() { return m_szDisplayName; }
|
||||
const char* GetTemplate() { return m_szTemplate; }
|
||||
};
|
||||
|
||||
typedef std::vector<ConfigTemplate*> ConfigTemplatesBase;
|
||||
|
||||
class ConfigTemplates: public ConfigTemplatesBase
|
||||
{
|
||||
public:
|
||||
~ConfigTemplates();
|
||||
};
|
||||
|
||||
typedef std::vector<char*> NameList;
|
||||
|
||||
class Category
|
||||
@@ -174,14 +152,12 @@ public:
|
||||
private:
|
||||
char* m_szName;
|
||||
char* m_szDestDir;
|
||||
char* m_szDefScript;
|
||||
|
||||
public:
|
||||
Category(const char* szName, const char* szDestDir, const char* szDefScript);
|
||||
Category(const char* szName, const char* szDestDir);
|
||||
~Category();
|
||||
const char* GetName() { return m_szName; }
|
||||
const char* GetDestDir() { return m_szDestDir; }
|
||||
const char* GetDefScript() { return m_szDefScript; }
|
||||
};
|
||||
|
||||
typedef std::vector<Category*> CategoriesBase;
|
||||
@@ -193,31 +169,6 @@ public:
|
||||
Category* FindCategory(const char* szName);
|
||||
};
|
||||
|
||||
class Script
|
||||
{
|
||||
private:
|
||||
char* m_szName;
|
||||
char* m_szLocation;
|
||||
char* m_szDisplayName;
|
||||
|
||||
public:
|
||||
Script(const char* szName, const char* szLocation);
|
||||
~Script();
|
||||
const char* GetName() { return m_szName; }
|
||||
const char* GetLocation() { return m_szLocation; }
|
||||
void SetDisplayName(const char* szDisplayName);
|
||||
const char* GetDisplayName() { return m_szDisplayName; }
|
||||
};
|
||||
|
||||
typedef std::list<Script*> ScriptListBase;
|
||||
|
||||
class ScriptList: public ScriptListBase
|
||||
{
|
||||
public:
|
||||
~ScriptList();
|
||||
Script* Find(const char* szName);
|
||||
};
|
||||
|
||||
private:
|
||||
OptEntries m_OptEntries;
|
||||
bool m_bConfigInitialized;
|
||||
@@ -234,8 +185,6 @@ private:
|
||||
char* m_szQueueDir;
|
||||
char* m_szNzbDir;
|
||||
char* m_szWebDir;
|
||||
char* m_szConfigTemplate;
|
||||
char* m_szScriptDir;
|
||||
EMessageTarget m_eInfoTarget;
|
||||
EMessageTarget m_eWarningTarget;
|
||||
EMessageTarget m_eErrorTarget;
|
||||
@@ -246,14 +195,15 @@ private:
|
||||
bool m_bResetLog;
|
||||
int m_iConnectionTimeout;
|
||||
int m_iTerminateTimeout;
|
||||
bool m_bAppendNZBDir;
|
||||
bool m_bAppendCategoryDir;
|
||||
bool m_bContinuePartial;
|
||||
bool m_bRenameBroken;
|
||||
int m_iRetries;
|
||||
int m_iRetryInterval;
|
||||
bool m_bSaveQueue;
|
||||
bool m_bDupeCheck;
|
||||
char* m_szControlIP;
|
||||
char* m_szControlUsername;
|
||||
char* m_szControlPassword;
|
||||
int m_iControlPort;
|
||||
bool m_bSecureControl;
|
||||
@@ -261,7 +211,7 @@ private:
|
||||
char* m_szSecureCert;
|
||||
char* m_szSecureKey;
|
||||
char* m_szLockFile;
|
||||
char* m_szDaemonUsername;
|
||||
char* m_szDaemonUserName;
|
||||
EOutputMode m_eOutputMode;
|
||||
bool m_bReloadQueue;
|
||||
bool m_bReloadUrlQueue;
|
||||
@@ -270,11 +220,12 @@ private:
|
||||
int m_iLogBufferSize;
|
||||
bool m_bCreateLog;
|
||||
char* m_szLogFile;
|
||||
EParCheck m_eParCheck;
|
||||
ELoadPars m_eLoadPars;
|
||||
bool m_bParCheck;
|
||||
bool m_bParRepair;
|
||||
EParScan m_eParScan;
|
||||
char* m_szDefScript;
|
||||
char* m_szScriptOrder;
|
||||
char* m_szPostProcess;
|
||||
char* m_szPostConfigFilename;
|
||||
char* m_szNZBProcess;
|
||||
char* m_szNZBAddedProcess;
|
||||
bool m_bStrictParName;
|
||||
@@ -285,16 +236,19 @@ private:
|
||||
bool m_bCursesTime;
|
||||
bool m_bCursesGroup;
|
||||
bool m_bCrcCheck;
|
||||
int m_iThreadLimit;
|
||||
bool m_bDirectWrite;
|
||||
int m_iWriteBufferSize;
|
||||
int m_iNzbDirInterval;
|
||||
int m_iNzbDirFileAge;
|
||||
bool m_bParCleanupQueue;
|
||||
int m_iDiskSpace;
|
||||
EScriptLogKind m_eProcessLogKind;
|
||||
bool m_bAllowReProcess;
|
||||
bool m_bTLS;
|
||||
bool m_bDumpCore;
|
||||
bool m_bParPauseQueue;
|
||||
bool m_bScriptPauseQueue;
|
||||
bool m_bPostPauseQueue;
|
||||
bool m_bNzbCleanupDisk;
|
||||
bool m_bDeleteCleanupDisk;
|
||||
bool m_bMergeNzb;
|
||||
@@ -306,7 +260,6 @@ private:
|
||||
char* m_szUnrarCmd;
|
||||
char* m_szSevenZipCmd;
|
||||
bool m_bUnpackPauseQueue;
|
||||
char* m_szExtCleanupDisk;
|
||||
|
||||
// Parsed command-line parameters
|
||||
bool m_bServerMode;
|
||||
@@ -345,6 +298,7 @@ private:
|
||||
void InitOptFile();
|
||||
void InitCommandLine(int argc, char* argv[]);
|
||||
void InitOptions();
|
||||
void InitPostConfig();
|
||||
void InitFileArg(int argc, char* argv[]);
|
||||
void InitServers();
|
||||
void InitCategories();
|
||||
@@ -369,19 +323,14 @@ private:
|
||||
void ConfigError(const char* msg, ...);
|
||||
void ConfigWarn(const char* msg, ...);
|
||||
void LocateOptionSrcPos(const char *szOptionName);
|
||||
void ConvertOldOption(char *szOption, int iOptionBufLen, char *szValue, int iValueBufLen);
|
||||
static bool CompareScripts(Script* pScript1, Script* pScript2);
|
||||
void LoadScriptDir(ScriptList* pScriptList, const char* szDirectory, bool bIsSubDir);
|
||||
void BuildScriptDisplayNames(ScriptList* pScriptList);
|
||||
void ConvertOldOptionName(char *szOption, int iBufLen);
|
||||
|
||||
public:
|
||||
Options(int argc, char* argv[]);
|
||||
~Options();
|
||||
|
||||
bool LoadConfig(OptEntries* pOptEntries);
|
||||
bool SaveConfig(OptEntries* pOptEntries);
|
||||
bool LoadConfigTemplates(ConfigTemplates* pConfigTemplates);
|
||||
void LoadScriptList(ScriptList* pScriptList);
|
||||
bool LoadConfig(EDomain eDomain, OptEntries* pOptEntries);
|
||||
bool SaveConfig(EDomain eDomain, OptEntries* pOptEntries);
|
||||
|
||||
// Options
|
||||
OptEntries* LockOptEntries();
|
||||
@@ -393,8 +342,6 @@ public:
|
||||
const char* GetQueueDir() { return m_szQueueDir; }
|
||||
const char* GetNzbDir() { return m_szNzbDir; }
|
||||
const char* GetWebDir() { return m_szWebDir; }
|
||||
const char* GetConfigTemplate() { return m_szConfigTemplate; }
|
||||
const char* GetScriptDir() { return m_szScriptDir; }
|
||||
bool GetCreateBrokenLog() const { return m_bCreateBrokenLog; }
|
||||
bool GetResetLog() const { return m_bResetLog; }
|
||||
EMessageTarget GetInfoTarget() const { return m_eInfoTarget; }
|
||||
@@ -405,14 +352,15 @@ public:
|
||||
int GetConnectionTimeout() { return m_iConnectionTimeout; }
|
||||
int GetTerminateTimeout() { return m_iTerminateTimeout; }
|
||||
bool GetDecode() { return m_bDecode; };
|
||||
bool GetAppendNZBDir() { return m_bAppendNZBDir; }
|
||||
bool GetAppendCategoryDir() { return m_bAppendCategoryDir; }
|
||||
bool GetContinuePartial() { return m_bContinuePartial; }
|
||||
bool GetRenameBroken() { return m_bRenameBroken; }
|
||||
int GetRetries() { return m_iRetries; }
|
||||
int GetRetryInterval() { return m_iRetryInterval; }
|
||||
bool GetSaveQueue() { return m_bSaveQueue; }
|
||||
bool GetDupeCheck() { return m_bDupeCheck; }
|
||||
const char* GetControlIP() { return m_szControlIP; }
|
||||
const char* GetControlUsername() { return m_szControlUsername; }
|
||||
const char* GetControlPassword() { return m_szControlPassword; }
|
||||
int GetControlPort() { return m_iControlPort; }
|
||||
bool GetSecureControl() { return m_bSecureControl; }
|
||||
@@ -420,7 +368,7 @@ public:
|
||||
const char* GetSecureCert() { return m_szSecureCert; }
|
||||
const char* GetSecureKey() { return m_szSecureKey; }
|
||||
const char* GetLockFile() { return m_szLockFile; }
|
||||
const char* GetDaemonUsername() { return m_szDaemonUsername; }
|
||||
const char* GetDaemonUserName() { return m_szDaemonUserName; }
|
||||
EOutputMode GetOutputMode() { return m_eOutputMode; }
|
||||
bool GetReloadQueue() { return m_bReloadQueue; }
|
||||
bool GetReloadUrlQueue() { return m_bReloadUrlQueue; }
|
||||
@@ -429,11 +377,12 @@ public:
|
||||
int GetLogBufferSize() { return m_iLogBufferSize; }
|
||||
bool GetCreateLog() { return m_bCreateLog; }
|
||||
const char* GetLogFile() { return m_szLogFile; }
|
||||
EParCheck GetParCheck() { return m_eParCheck; }
|
||||
ELoadPars GetLoadPars() { return m_eLoadPars; }
|
||||
bool GetParCheck() { return m_bParCheck; }
|
||||
bool GetParRepair() { return m_bParRepair; }
|
||||
EParScan GetParScan() { return m_eParScan; }
|
||||
const char* GetScriptOrder() { return m_szScriptOrder; }
|
||||
const char* GetDefScript() { return m_szDefScript; }
|
||||
const char* GetPostProcess() { return m_szPostProcess; }
|
||||
const char* GetPostConfigFilename() { return m_szPostConfigFilename; }
|
||||
const char* GetNZBProcess() { return m_szNZBProcess; }
|
||||
const char* GetNZBAddedProcess() { return m_szNZBAddedProcess; }
|
||||
bool GetStrictParName() { return m_bStrictParName; }
|
||||
@@ -443,16 +392,19 @@ public:
|
||||
bool GetCursesTime() { return m_bCursesTime; }
|
||||
bool GetCursesGroup() { return m_bCursesGroup; }
|
||||
bool GetCrcCheck() { return m_bCrcCheck; }
|
||||
int GetThreadLimit() { return m_iThreadLimit; }
|
||||
bool GetDirectWrite() { return m_bDirectWrite; }
|
||||
int GetWriteBufferSize() { return m_iWriteBufferSize; }
|
||||
int GetNzbDirInterval() { return m_iNzbDirInterval; }
|
||||
int GetNzbDirFileAge() { return m_iNzbDirFileAge; }
|
||||
bool GetParCleanupQueue() { return m_bParCleanupQueue; }
|
||||
int GetDiskSpace() { return m_iDiskSpace; }
|
||||
EScriptLogKind GetProcessLogKind() { return m_eProcessLogKind; }
|
||||
bool GetAllowReProcess() { return m_bAllowReProcess; }
|
||||
bool GetTLS() { return m_bTLS; }
|
||||
bool GetDumpCore() { return m_bDumpCore; }
|
||||
bool GetParPauseQueue() { return m_bParPauseQueue; }
|
||||
bool GetScriptPauseQueue() { return m_bScriptPauseQueue; }
|
||||
bool GetPostPauseQueue() { return m_bPostPauseQueue; }
|
||||
bool GetNzbCleanupDisk() { return m_bNzbCleanupDisk; }
|
||||
bool GetDeleteCleanupDisk() { return m_bDeleteCleanupDisk; }
|
||||
bool GetMergeNzb() { return m_bMergeNzb; }
|
||||
@@ -464,7 +416,6 @@ public:
|
||||
const char* GetUnrarCmd() { return m_szUnrarCmd; }
|
||||
const char* GetSevenZipCmd() { return m_szSevenZipCmd; }
|
||||
bool GetUnpackPauseQueue() { return m_bUnpackPauseQueue; }
|
||||
const char* GetExtCleanupDisk() { return m_szExtCleanupDisk; }
|
||||
|
||||
Category* FindCategory(const char* szName) { return m_Categories.FindCategory(szName); }
|
||||
|
||||
|
||||
274
ParChecker.cpp
274
ParChecker.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -35,8 +35,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <par2cmdline.h>
|
||||
#include <par2repairer.h>
|
||||
@@ -45,11 +45,9 @@
|
||||
#include <libpar2/par2cmdline.h>
|
||||
#include <libpar2/par2repairer.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "ParChecker.h"
|
||||
#include "ParCoordinator.h"
|
||||
#include "Log.h"
|
||||
#include "Options.h"
|
||||
#include "Util.h"
|
||||
@@ -79,6 +77,7 @@ public:
|
||||
friend class ParChecker;
|
||||
};
|
||||
|
||||
|
||||
Result Repairer::PreProcess(const char *szParFilename)
|
||||
{
|
||||
#ifdef HAVE_PAR2_BUGFIXES_V2
|
||||
@@ -156,9 +155,7 @@ ParChecker::ParChecker()
|
||||
{
|
||||
debug("Creating ParChecker");
|
||||
|
||||
m_eStatus = psFailed;
|
||||
m_szDestDir = NULL;
|
||||
m_szNZBName = NULL;
|
||||
m_eStatus = psUndefined;
|
||||
m_szParFilename = NULL;
|
||||
m_szInfoName = NULL;
|
||||
m_szErrMsg = NULL;
|
||||
@@ -175,13 +172,9 @@ ParChecker::~ParChecker()
|
||||
{
|
||||
debug("Destroying ParChecker");
|
||||
|
||||
if (m_szDestDir)
|
||||
if (m_szParFilename)
|
||||
{
|
||||
free(m_szDestDir);
|
||||
}
|
||||
if (m_szNZBName)
|
||||
{
|
||||
free(m_szNZBName);
|
||||
free(m_szParFilename);
|
||||
}
|
||||
if (m_szInfoName)
|
||||
{
|
||||
@@ -209,26 +202,15 @@ void ParChecker::Cleanup()
|
||||
free(*it);
|
||||
}
|
||||
m_ProcessedFiles.clear();
|
||||
|
||||
m_sourceFiles.clear();
|
||||
}
|
||||
|
||||
void ParChecker::SetDestDir(const char * szDestDir)
|
||||
void ParChecker::SetParFilename(const char * szParFilename)
|
||||
{
|
||||
if (m_szDestDir)
|
||||
if (m_szParFilename)
|
||||
{
|
||||
free(m_szDestDir);
|
||||
free(m_szParFilename);
|
||||
}
|
||||
m_szDestDir = strdup(szDestDir);
|
||||
}
|
||||
|
||||
void ParChecker::SetNZBName(const char * szNZBName)
|
||||
{
|
||||
if (m_szNZBName)
|
||||
{
|
||||
free(m_szNZBName);
|
||||
}
|
||||
m_szNZBName = strdup(szNZBName);
|
||||
m_szParFilename = strdup(szParFilename);
|
||||
}
|
||||
|
||||
void ParChecker::SetInfoName(const char * szInfoName)
|
||||
@@ -240,118 +222,24 @@ void ParChecker::SetInfoName(const char * szInfoName)
|
||||
m_szInfoName = strdup(szInfoName);
|
||||
}
|
||||
|
||||
void ParChecker::SetStatus(EStatus eStatus)
|
||||
{
|
||||
m_eStatus = eStatus;
|
||||
Notify(NULL);
|
||||
}
|
||||
|
||||
void ParChecker::Run()
|
||||
{
|
||||
ParCoordinator::FileList fileList;
|
||||
if (!ParCoordinator::FindMainPars(m_szDestDir, &fileList))
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not start par-check for %s. Could not find any par-files", m_szNZBName);
|
||||
m_eStatus = psFailed;
|
||||
Completed();
|
||||
return;
|
||||
}
|
||||
|
||||
m_eStatus = psRepairNotNeeded;
|
||||
m_bCancelled = false;
|
||||
|
||||
for (ParCoordinator::FileList::iterator it = fileList.begin(); it != fileList.end(); it++)
|
||||
{
|
||||
char* szParFilename = *it;
|
||||
debug("Found par: %s", szParFilename);
|
||||
|
||||
if (!IsStopped() && !m_bCancelled)
|
||||
{
|
||||
char szFullParFilename[1024];
|
||||
snprintf(szFullParFilename, 1024, "%s%c%s", m_szDestDir, (int)PATH_SEPARATOR, szParFilename);
|
||||
szFullParFilename[1024-1] = '\0';
|
||||
|
||||
char szInfoName[1024];
|
||||
int iBaseLen = 0;
|
||||
ParCoordinator::ParseParFilename(szParFilename, &iBaseLen, NULL);
|
||||
int maxlen = iBaseLen < 1024 ? iBaseLen : 1024 - 1;
|
||||
strncpy(szInfoName, szParFilename, maxlen);
|
||||
szInfoName[maxlen] = '\0';
|
||||
|
||||
char szParInfoName[1024];
|
||||
snprintf(szParInfoName, 1024, "%s%c%s", m_szNZBName, (int)PATH_SEPARATOR, szInfoName);
|
||||
szParInfoName[1024-1] = '\0';
|
||||
|
||||
SetInfoName(szParInfoName);
|
||||
|
||||
EStatus eStatus = RunParCheck(szFullParFilename);
|
||||
|
||||
// accumulate total status, the worst status has priority
|
||||
if (m_eStatus > eStatus)
|
||||
{
|
||||
m_eStatus = eStatus;
|
||||
}
|
||||
|
||||
if (g_pOptions->GetCreateBrokenLog())
|
||||
{
|
||||
WriteBrokenLog(eStatus);
|
||||
}
|
||||
}
|
||||
|
||||
free(szParFilename);
|
||||
}
|
||||
|
||||
Completed();
|
||||
}
|
||||
|
||||
void ParChecker::WriteBrokenLog(EStatus eStatus)
|
||||
{
|
||||
char szBrokenLogName[1024];
|
||||
snprintf(szBrokenLogName, 1024, "%s%c_brokenlog.txt", m_szDestDir, (int)PATH_SEPARATOR);
|
||||
szBrokenLogName[1024-1] = '\0';
|
||||
|
||||
if (eStatus != psRepairNotNeeded || Util::FileExists(szBrokenLogName))
|
||||
{
|
||||
FILE* file = fopen(szBrokenLogName, "ab");
|
||||
if (file)
|
||||
{
|
||||
if (eStatus == psFailed)
|
||||
{
|
||||
if (m_bCancelled)
|
||||
{
|
||||
fprintf(file, "Repair cancelled for %s\n", m_szInfoName);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "Repair failed for %s: %s\n", m_szInfoName, m_szErrMsg ? m_szErrMsg : "");
|
||||
}
|
||||
}
|
||||
else if (eStatus == psRepairPossible)
|
||||
{
|
||||
fprintf(file, "Repair possible for %s\n", m_szInfoName);
|
||||
}
|
||||
else if (eStatus == psRepaired)
|
||||
{
|
||||
fprintf(file, "Successfully repaired %s\n", m_szInfoName);
|
||||
}
|
||||
else if (eStatus == psRepairNotNeeded)
|
||||
{
|
||||
fprintf(file, "Repair not needed for %s\n", m_szInfoName);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not open file %s", szBrokenLogName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParChecker::EStatus ParChecker::RunParCheck(const char* szParFilename)
|
||||
{
|
||||
Cleanup();
|
||||
m_szParFilename = szParFilename;
|
||||
m_bRepairNotNeeded = false;
|
||||
m_eStage = ptLoadingPars;
|
||||
m_iProcessedFiles = 0;
|
||||
m_iExtraFiles = 0;
|
||||
m_bVerifyingExtraFiles = false;
|
||||
EStatus eStatus = psFailed;
|
||||
m_bCancelled = false;
|
||||
|
||||
PrintMessage(Message::mkInfo, "Verifying %s", m_szInfoName);
|
||||
info("Verifying %s", m_szInfoName);
|
||||
SetStatus(psWorking);
|
||||
|
||||
debug("par: %s", m_szParFilename);
|
||||
|
||||
@@ -377,17 +265,18 @@ ParChecker::EStatus ParChecker::RunParCheck(const char* szParFilename)
|
||||
{
|
||||
if (res == eInvalidCommandLineArguments)
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not start par-check for %s. Par-file: %s", m_szInfoName, m_szParFilename);
|
||||
error("Could not start par-check for %s. Par-file: %s", m_szInfoName, m_szParFilename);
|
||||
m_szErrMsg = strdup("Command line could not be parsed");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not verify %s: %s", m_szInfoName, IsStopped() ? "due stopping" : "par2-file could not be processed");
|
||||
error("Could not verify %s: %s", m_szInfoName, IsStopped() ? "due stopping" : "par2-file could not be processed");
|
||||
m_szErrMsg = strdup("par2-file could not be processed");
|
||||
}
|
||||
SetStatus(psFailed);
|
||||
delete pRepairer;
|
||||
Cleanup();
|
||||
return psFailed;
|
||||
return;
|
||||
}
|
||||
|
||||
char BufReason[1024];
|
||||
@@ -421,7 +310,7 @@ ParChecker::EStatus ParChecker::RunParCheck(const char* szParFilename)
|
||||
int missingblockcount = pRepairer->missingblockcount - pRepairer->recoverypacketmap.size();
|
||||
if (bMoreFilesLoaded)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Need more %i par-block(s) for %s", missingblockcount, m_szInfoName);
|
||||
info("Need more %i par-block(s) for %s", missingblockcount, m_szInfoName);
|
||||
}
|
||||
|
||||
m_mutexQueuedParFiles.Lock();
|
||||
@@ -483,26 +372,23 @@ ParChecker::EStatus ParChecker::RunParCheck(const char* szParFilename)
|
||||
|
||||
if (IsStopped())
|
||||
{
|
||||
SetStatus(psFailed);
|
||||
delete pRepairer;
|
||||
Cleanup();
|
||||
return psFailed;
|
||||
return;
|
||||
}
|
||||
|
||||
eStatus = psFailed;
|
||||
|
||||
if (res == eSuccess)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Repair not needed for %s", m_szInfoName);
|
||||
eStatus = psRepairNotNeeded;
|
||||
info("Repair not needed for %s", m_szInfoName);
|
||||
m_bRepairNotNeeded = true;
|
||||
}
|
||||
else if (res == eRepairPossible)
|
||||
{
|
||||
eStatus = psRepairPossible;
|
||||
if (g_pOptions->GetParRepair())
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Repairing %s", m_szInfoName);
|
||||
info("Repairing %s", m_szInfoName);
|
||||
|
||||
SaveSourceList();
|
||||
snprintf(m_szProgressLabel, 1024, "Repairing %s", m_szInfoName);
|
||||
m_szProgressLabel[1024-1] = '\0';
|
||||
m_iFileProgress = 0;
|
||||
@@ -516,44 +402,38 @@ ParChecker::EStatus ParChecker::RunParCheck(const char* szParFilename)
|
||||
debug("ParChecker: Process-result=%i", res);
|
||||
if (res == eSuccess)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Successfully repaired %s", m_szInfoName);
|
||||
eStatus = psRepaired;
|
||||
DeleteLeftovers();
|
||||
info("Successfully repaired %s", m_szInfoName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Repair possible for %s", m_szInfoName);
|
||||
info("Repair possible for %s", m_szInfoName);
|
||||
res = eSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bCancelled)
|
||||
{
|
||||
if (m_eStage >= ptRepairing)
|
||||
{
|
||||
PrintMessage(Message::mkWarning, "Repair cancelled for %s", m_szInfoName);
|
||||
m_szErrMsg = strdup("repair cancelled");
|
||||
eStatus = psRepairPossible;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkWarning, "Par-check cancelled for %s", m_szInfoName);
|
||||
m_szErrMsg = strdup("par-check cancelled");
|
||||
eStatus = psFailed;
|
||||
}
|
||||
warn("Repair cancelled for %s", m_szInfoName);
|
||||
m_szErrMsg = strdup("repair cancelled");
|
||||
SetStatus(psFailed);
|
||||
}
|
||||
else if (eStatus == psFailed)
|
||||
else if (res == eSuccess)
|
||||
{
|
||||
SetStatus(psFinished);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_szErrMsg && (int)res >= 0 && (int)res <= 8)
|
||||
{
|
||||
m_szErrMsg = strdup(Par2CmdLineErrStr[res]);
|
||||
}
|
||||
PrintMessage(Message::mkError, "Repair failed for %s: %s", m_szInfoName, m_szErrMsg ? m_szErrMsg : "");
|
||||
error("Repair failed for %s: %s", m_szInfoName, m_szErrMsg ? m_szErrMsg : "");
|
||||
SetStatus(psFailed);
|
||||
}
|
||||
|
||||
delete pRepairer;
|
||||
Cleanup();
|
||||
return eStatus;
|
||||
}
|
||||
|
||||
bool ParChecker::LoadMorePars()
|
||||
@@ -570,11 +450,11 @@ bool ParChecker::LoadMorePars()
|
||||
bool loadedOK = ((Repairer*)m_pRepairer)->LoadPacketsFromFile(szParFilename);
|
||||
if (loadedOK)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "File %s successfully loaded for par-check", Util::BaseFileName(szParFilename), m_szInfoName);
|
||||
info("File %s successfully loaded for par-check", Util::BaseFileName(szParFilename), m_szInfoName);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Could not load file %s for par-check", Util::BaseFileName(szParFilename), m_szInfoName);
|
||||
info("Could not load file %s for par-check", Util::BaseFileName(szParFilename), m_szInfoName);
|
||||
}
|
||||
free(szParFilename);
|
||||
}
|
||||
@@ -605,7 +485,7 @@ bool ParChecker::CheckSplittedFragments()
|
||||
it != ((Repairer*)m_pRepairer)->sourcefiles.end(); it++)
|
||||
{
|
||||
Par2RepairerSourceFile *sourcefile = *it;
|
||||
if (AddSplittedFragments(sourcefile->TargetFileName().c_str()))
|
||||
if (!sourcefile->GetTargetExists() && AddSplittedFragments(sourcefile->TargetFileName().c_str()))
|
||||
{
|
||||
bFragmentsAdded = true;
|
||||
}
|
||||
@@ -669,7 +549,7 @@ bool ParChecker::AddSplittedFragments(const char* szFilename)
|
||||
|
||||
bool ParChecker::AddMissingFiles()
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Performing extra par-scan for %s", m_szInfoName);
|
||||
info("Performing extra par-scan for %s", m_szInfoName);
|
||||
|
||||
char szDirectory[1024];
|
||||
strncpy(szDirectory, m_szParFilename, 1024);
|
||||
@@ -763,7 +643,7 @@ void ParChecker::signal_filename(std::string str)
|
||||
m_eStage = ptVerifyingRepaired;
|
||||
}
|
||||
|
||||
PrintMessage(Message::mkInfo, "%s %s", szStageMessage[m_eStage], str.c_str());
|
||||
info("%s %s", szStageMessage[m_eStage], str.c_str());
|
||||
|
||||
if (m_eStage == ptLoadingPars || m_eStage == ptVerifyingSources)
|
||||
{
|
||||
@@ -847,11 +727,11 @@ void ParChecker::signal_done(std::string str, int available, int total)
|
||||
|
||||
if (bFileExists)
|
||||
{
|
||||
PrintMessage(Message::mkWarning, "File %s has %i bad block(s) of total %i block(s)", str.c_str(), total - available, total);
|
||||
warn("File %s has %i bad block(s) of total %i block(s)", str.c_str(), total - available, total);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkWarning, "File %s with %i block(s) is missing", str.c_str(), total);
|
||||
warn("File %s with %i block(s) is missing", str.c_str(), total);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -863,60 +743,8 @@ void ParChecker::Cancel()
|
||||
((Repairer*)m_pRepairer)->cancelled = true;
|
||||
m_bCancelled = true;
|
||||
#else
|
||||
PrintMessage(Message::mkError, "Could not cancel par-repair. The program was compiled using version of libpar2 which doesn't support cancelling of par-repair. Please apply libpar2-patches supplied with NZBGet and recompile libpar2 and NZBGet (see README for details).");
|
||||
error("Could not cancel par-repair. The program was compiled using version of libpar2 which doesn't support cancelling of par-repair. Please apply libpar2-patches supplied with NZBGet and recompile libpar2 and NZBGet (see README for details).");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParChecker::SaveSourceList()
|
||||
{
|
||||
// Buliding a list of DiskFile-objects, marked as source-files
|
||||
|
||||
for (std::vector<Par2RepairerSourceFile*>::iterator it = ((Repairer*)m_pRepairer)->sourcefiles.begin();
|
||||
it != ((Repairer*)m_pRepairer)->sourcefiles.end(); it++)
|
||||
{
|
||||
Par2RepairerSourceFile* sourcefile = (Par2RepairerSourceFile*)*it;
|
||||
vector<DataBlock>::iterator it2 = sourcefile->SourceBlocks();
|
||||
for (int i = 0; i < (int)sourcefile->BlockCount(); i++, it2++)
|
||||
{
|
||||
DataBlock block = *it2;
|
||||
DiskFile* pSourceFile = block.GetDiskFile();
|
||||
if (pSourceFile &&
|
||||
std::find(m_sourceFiles.begin(), m_sourceFiles.end(), pSourceFile) == m_sourceFiles.end())
|
||||
{
|
||||
m_sourceFiles.push_back(pSourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParChecker::DeleteLeftovers()
|
||||
{
|
||||
// After repairing check if all DiskFile-objects saved by "SaveSourceList()" have
|
||||
// corresponding target-files. If not - the source file was replaced. In this case
|
||||
// the DiskFile-object points to the renamed bak-file, which we can delete.
|
||||
|
||||
for (SourceList::iterator it = m_sourceFiles.begin(); it != m_sourceFiles.end(); it++)
|
||||
{
|
||||
DiskFile* pSourceFile = (DiskFile*)*it;
|
||||
|
||||
bool bFound = false;
|
||||
for (std::vector<Par2RepairerSourceFile*>::iterator it2 = ((Repairer*)m_pRepairer)->sourcefiles.begin();
|
||||
it2 != ((Repairer*)m_pRepairer)->sourcefiles.end(); it2++)
|
||||
{
|
||||
Par2RepairerSourceFile* sourcefile = *it2;
|
||||
if (sourcefile->GetTargetFile() == pSourceFile)
|
||||
{
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Deleting file %s", Util::BaseFileName(pSourceFile->FileName().c_str()));
|
||||
remove(pSourceFile->FileName().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
32
ParChecker.h
32
ParChecker.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,20 +29,19 @@
|
||||
#ifndef DISABLE_PARCHECK
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Log.h"
|
||||
#include "Observer.h"
|
||||
|
||||
class ParChecker : public Thread
|
||||
class ParChecker : public Thread, public Subject
|
||||
{
|
||||
public:
|
||||
enum EStatus
|
||||
{
|
||||
psUndefined,
|
||||
psWorking,
|
||||
psFailed,
|
||||
psRepairPossible,
|
||||
psRepaired,
|
||||
psRepairNotNeeded
|
||||
psFinished
|
||||
};
|
||||
|
||||
enum EStage
|
||||
@@ -54,17 +53,15 @@ public:
|
||||
};
|
||||
|
||||
typedef std::deque<char*> FileList;
|
||||
typedef std::deque<void*> SourceList;
|
||||
|
||||
private:
|
||||
char* m_szInfoName;
|
||||
char* m_szDestDir;
|
||||
char* m_szNZBName;
|
||||
const char* m_szParFilename;
|
||||
char* m_szParFilename;
|
||||
EStatus m_eStatus;
|
||||
EStage m_eStage;
|
||||
void* m_pRepairer; // declared as void* to prevent the including of libpar2-headers into this header-file
|
||||
char* m_szErrMsg;
|
||||
bool m_bRepairNotNeeded;
|
||||
FileList m_QueuedParFiles;
|
||||
Mutex m_mutexQueuedParFiles;
|
||||
bool m_bQueuedParFilesChanged;
|
||||
@@ -77,17 +74,12 @@ private:
|
||||
int m_iFileProgress;
|
||||
int m_iStageProgress;
|
||||
bool m_bCancelled;
|
||||
SourceList m_sourceFiles;
|
||||
|
||||
EStatus RunParCheck(const char* szParFilename);
|
||||
void WriteBrokenLog(EStatus eStatus);
|
||||
void Cleanup();
|
||||
bool LoadMorePars();
|
||||
bool CheckSplittedFragments();
|
||||
bool AddSplittedFragments(const char* szFilename);
|
||||
bool AddMissingFiles();
|
||||
void SaveSourceList();
|
||||
void DeleteLeftovers();
|
||||
void signal_filename(std::string str);
|
||||
void signal_progress(double progress);
|
||||
void signal_done(std::string str, int available, int total);
|
||||
@@ -100,8 +92,6 @@ protected:
|
||||
*/
|
||||
virtual bool RequestMorePars(int iBlockNeeded, int* pBlockFound) = 0;
|
||||
virtual void UpdateProgress() {}
|
||||
virtual void Completed() {}
|
||||
virtual void PrintMessage(Message::EKind eKind, const char* szFormat, ...) {}
|
||||
EStage GetStage() { return m_eStage; }
|
||||
const char* GetProgressLabel() { return m_szProgressLabel; }
|
||||
int GetFileProgress() { return m_iFileProgress; }
|
||||
@@ -111,12 +101,14 @@ public:
|
||||
ParChecker();
|
||||
virtual ~ParChecker();
|
||||
virtual void Run();
|
||||
void SetDestDir(const char* szDestDir);
|
||||
const char* GetParFilename() { return m_szParFilename; }
|
||||
void SetParFilename(const char* szParFilename);
|
||||
const char* GetInfoName() { return m_szInfoName; }
|
||||
void SetInfoName(const char* szInfoName);
|
||||
void SetNZBName(const char* szNZBName);
|
||||
void SetStatus(EStatus eStatus);
|
||||
EStatus GetStatus() { return m_eStatus; }
|
||||
const char* GetErrMsg() { return m_szErrMsg; }
|
||||
bool GetRepairNotNeeded() { return m_bRepairNotNeeded; }
|
||||
void AddParFile(const char* szParFilename);
|
||||
void QueueChanged();
|
||||
void Cancel();
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
@@ -64,34 +63,10 @@ void ParCoordinator::PostParChecker::UpdateProgress()
|
||||
m_pOwner->UpdateParCheckProgress();
|
||||
}
|
||||
|
||||
void ParCoordinator::PostParChecker::PrintMessage(Message::EKind eKind, const char* szFormat, ...)
|
||||
{
|
||||
char szText[1024];
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
vsnprintf(szText, 1024, szFormat, args);
|
||||
va_end(args);
|
||||
szText[1024-1] = '\0';
|
||||
|
||||
m_pOwner->PrintMessage(m_pPostInfo, eKind, "%s", szText);
|
||||
}
|
||||
|
||||
void ParCoordinator::PostParRenamer::UpdateProgress()
|
||||
{
|
||||
m_pOwner->UpdateParRenameProgress();
|
||||
}
|
||||
|
||||
void ParCoordinator::PostParRenamer::PrintMessage(Message::EKind eKind, const char* szFormat, ...)
|
||||
{
|
||||
char szText[1024];
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
vsnprintf(szText, 1024, szFormat, args);
|
||||
va_end(args);
|
||||
szText[1024-1] = '\0';
|
||||
|
||||
m_pOwner->PrintMessage(m_pPostInfo, eKind, "%s", szText);
|
||||
}
|
||||
#endif
|
||||
|
||||
ParCoordinator::ParCoordinator()
|
||||
@@ -99,9 +74,18 @@ ParCoordinator::ParCoordinator()
|
||||
debug("Creating ParCoordinator");
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
m_bStopped = false;
|
||||
m_ParCheckerObserver.m_pOwner = this;
|
||||
m_ParChecker.Attach(&m_ParCheckerObserver);
|
||||
m_ParChecker.m_pOwner = this;
|
||||
|
||||
m_ParRenamerObserver.m_pOwner = this;
|
||||
m_ParRenamer.Attach(&m_ParRenamerObserver);
|
||||
m_ParRenamer.m_pOwner = this;
|
||||
|
||||
m_bStopped = false;
|
||||
|
||||
const char* szPostScript = g_pOptions->GetPostProcess();
|
||||
m_bPostScript = szPostScript && strlen(szPostScript) > 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -145,7 +129,10 @@ void ParCoordinator::PausePars(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo)
|
||||
if (pFileInfo->GetNZBInfo() == pNZBInfo)
|
||||
{
|
||||
g_pQueueCoordinator->GetQueueEditor()->LockedEditEntry(pDownloadQueue, pFileInfo->GetID(), false,
|
||||
QueueEditor::eaGroupPauseExtraPars, 0, NULL);
|
||||
(g_pOptions->GetLoadPars() == Options::lpOne ||
|
||||
(g_pOptions->GetLoadPars() == Options::lpNone && g_pOptions->GetParCheck()))
|
||||
? QueueEditor::eaGroupPauseExtraPars : QueueEditor::eaGroupPauseAllPars,
|
||||
0, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -258,11 +245,11 @@ bool ParCoordinator::ParseParFilename(const char* szParFilename, int* iBaseNameL
|
||||
*/
|
||||
void ParCoordinator::StartParCheckJob(PostInfo* pPostInfo)
|
||||
{
|
||||
info("Checking pars for %s", pPostInfo->GetInfoName());
|
||||
m_eCurrentJob = jkParCheck;
|
||||
m_ParChecker.SetPostInfo(pPostInfo);
|
||||
m_ParChecker.SetDestDir(pPostInfo->GetNZBInfo()->GetDestDir());
|
||||
m_ParChecker.SetNZBName(pPostInfo->GetNZBInfo()->GetName());
|
||||
m_ParChecker.PrintMessage(Message::mkInfo, "Checking pars for %s", pPostInfo->GetInfoName());
|
||||
m_ParChecker.SetParFilename(pPostInfo->GetParFilename());
|
||||
m_ParChecker.SetInfoName(pPostInfo->GetInfoName());
|
||||
pPostInfo->SetWorking(true);
|
||||
m_ParChecker.Start();
|
||||
}
|
||||
@@ -272,11 +259,11 @@ void ParCoordinator::StartParCheckJob(PostInfo* pPostInfo)
|
||||
*/
|
||||
void ParCoordinator::StartParRenameJob(PostInfo* pPostInfo)
|
||||
{
|
||||
info("Checking renamed files for %s", pPostInfo->GetNZBInfo()->GetName());
|
||||
m_eCurrentJob = jkParRename;
|
||||
m_ParRenamer.SetPostInfo(pPostInfo);
|
||||
m_ParRenamer.SetDestDir(pPostInfo->GetNZBInfo()->GetDestDir());
|
||||
m_ParRenamer.SetInfoName(pPostInfo->GetNZBInfo()->GetName());
|
||||
m_ParRenamer.PrintMessage(Message::mkInfo, "Checking renamed files for %s", pPostInfo->GetNZBInfo()->GetName());
|
||||
pPostInfo->SetWorking(true);
|
||||
m_ParRenamer.Start();
|
||||
}
|
||||
@@ -335,38 +322,106 @@ bool ParCoordinator::AddPar(FileInfo* pFileInfo, bool bDeleted)
|
||||
return bSameCollection;
|
||||
}
|
||||
|
||||
void ParCoordinator::ParCheckCompleted()
|
||||
void ParCoordinator::ParCheckerUpdate(Subject* Caller, void* Aspect)
|
||||
{
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
PostInfo* pPostInfo = m_ParChecker.GetPostInfo();
|
||||
|
||||
// Update ParStatus (accumulate result)
|
||||
if ((m_ParChecker.GetStatus() == ParChecker::psRepaired ||
|
||||
m_ParChecker.GetStatus() == ParChecker::psRepairNotNeeded) &&
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped)
|
||||
if (m_ParChecker.GetStatus() == ParChecker::psFinished ||
|
||||
m_ParChecker.GetStatus() == ParChecker::psFailed)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psSuccess);
|
||||
}
|
||||
else if (m_ParChecker.GetStatus() == ParChecker::psRepairPossible &&
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psRepairPossible);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psFailure);
|
||||
}
|
||||
char szPath[1024];
|
||||
strncpy(szPath, m_ParChecker.GetParFilename(), 1024);
|
||||
szPath[1024-1] = '\0';
|
||||
if (char* p = strrchr(szPath, PATH_SEPARATOR)) *p = '\0';
|
||||
|
||||
pPostInfo->SetWorking(false);
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
if (g_pOptions->GetCreateBrokenLog())
|
||||
{
|
||||
char szBrokenLogName[1024];
|
||||
snprintf(szBrokenLogName, 1024, "%s%c_brokenlog.txt", szPath, (int)PATH_SEPARATOR);
|
||||
szBrokenLogName[1024-1] = '\0';
|
||||
|
||||
if (!m_ParChecker.GetRepairNotNeeded() || Util::FileExists(szBrokenLogName))
|
||||
{
|
||||
FILE* file = fopen(szBrokenLogName, "ab");
|
||||
if (file)
|
||||
{
|
||||
if (m_ParChecker.GetStatus() == ParChecker::psFailed)
|
||||
{
|
||||
if (m_ParChecker.GetCancelled())
|
||||
{
|
||||
fprintf(file, "Repair cancelled for %s\n", m_ParChecker.GetInfoName());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "Repair failed for %s: %s\n", m_ParChecker.GetInfoName(), m_ParChecker.GetErrMsg() ? m_ParChecker.GetErrMsg() : "");
|
||||
}
|
||||
}
|
||||
else if (m_ParChecker.GetRepairNotNeeded())
|
||||
{
|
||||
fprintf(file, "Repair not needed for %s\n", m_ParChecker.GetInfoName());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_pOptions->GetParRepair())
|
||||
{
|
||||
fprintf(file, "Successfully repaired %s\n", m_ParChecker.GetInfoName());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "Repair possible for %s\n", m_ParChecker.GetInfoName());
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not open file %s", szBrokenLogName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->SaveDownloadQueue(pDownloadQueue);
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
PostInfo* pPostInfo = m_ParChecker.GetPostInfo();
|
||||
pPostInfo->SetWorking(false);
|
||||
if (pPostInfo->GetDeleted())
|
||||
{
|
||||
pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
}
|
||||
|
||||
// Update ParStatus by NZBInfo (accumulate result)
|
||||
if (m_ParChecker.GetStatus() == ParChecker::psFailed && !m_ParChecker.GetCancelled())
|
||||
{
|
||||
pPostInfo->SetParStatus(PostInfo::psFailure);
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psFailure);
|
||||
}
|
||||
else if (m_ParChecker.GetStatus() == ParChecker::psFinished &&
|
||||
(g_pOptions->GetParRepair() || m_ParChecker.GetRepairNotNeeded()))
|
||||
{
|
||||
pPostInfo->SetParStatus(PostInfo::psSuccess);
|
||||
if (pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psNone)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psSuccess);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pPostInfo->SetParStatus(PostInfo::psRepairPossible);
|
||||
if (pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psRepairPossible);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->SaveDownloadQueue(pDownloadQueue);
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,7 +473,7 @@ bool ParCoordinator::RequestMorePars(NZBInfo* pNZBInfo, const char* szParFilenam
|
||||
{
|
||||
if (pBestBlockInfo->m_pFileInfo->GetPaused())
|
||||
{
|
||||
m_ParChecker.PrintMessage(Message::mkInfo, "Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBestBlockInfo->m_pFileInfo->GetFilename());
|
||||
info("Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBestBlockInfo->m_pFileInfo->GetFilename());
|
||||
pBestBlockInfo->m_pFileInfo->SetPaused(false);
|
||||
pBestBlockInfo->m_pFileInfo->SetExtraPriority(true);
|
||||
}
|
||||
@@ -442,7 +497,7 @@ bool ParCoordinator::RequestMorePars(NZBInfo* pNZBInfo, const char* szParFilenam
|
||||
BlockInfo* pBlockInfo = blocks.front();
|
||||
if (pBlockInfo->m_pFileInfo->GetPaused())
|
||||
{
|
||||
m_ParChecker.PrintMessage(Message::mkInfo, "Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBlockInfo->m_pFileInfo->GetFilename());
|
||||
info("Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBlockInfo->m_pFileInfo->GetFilename());
|
||||
pBlockInfo->m_pFileInfo->SetPaused(false);
|
||||
pBlockInfo->m_pFileInfo->SetExtraPriority(true);
|
||||
}
|
||||
@@ -560,9 +615,9 @@ void ParCoordinator::FindPars(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo,
|
||||
|
||||
void ParCoordinator::UpdateParCheckProgress()
|
||||
{
|
||||
g_pQueueCoordinator->LockQueue();
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
PostInfo* pPostInfo = m_ParChecker.GetPostInfo();
|
||||
PostInfo* pPostInfo = pDownloadQueue->GetPostQueue()->front();
|
||||
if (m_ParChecker.GetFileProgress() == 0)
|
||||
{
|
||||
pPostInfo->SetProgressLabel(m_ParChecker.GetProgressLabel());
|
||||
@@ -599,7 +654,7 @@ void ParCoordinator::UpdateParCheckProgress()
|
||||
if (iEstimatedRepairTime > g_pOptions->GetParTimeLimit() * 60)
|
||||
{
|
||||
debug("Estimated repair time %i seconds", iEstimatedRepairTime);
|
||||
m_ParChecker.PrintMessage(Message::mkWarning, "Cancelling par-repair for %s, estimated repair time (%i minutes) exceeds allowed repair time", m_ParChecker.GetInfoName(), iEstimatedRepairTime / 60);
|
||||
warn("Cancelling par-repair for %s, estimated repair time (%i minutes) exceeds allowed repair time", m_ParChecker.GetInfoName(), iEstimatedRepairTime / 60);
|
||||
bParCancel = true;
|
||||
}
|
||||
}
|
||||
@@ -646,28 +701,50 @@ void ParCoordinator::CheckPauseState(PostInfo* pPostInfo)
|
||||
}
|
||||
}
|
||||
|
||||
void ParCoordinator::ParRenameCompleted()
|
||||
void ParCoordinator::ParRenamerUpdate(Subject* Caller, void* Aspect)
|
||||
{
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
PostInfo* pPostInfo = m_ParRenamer.GetPostInfo();
|
||||
pPostInfo->GetNZBInfo()->SetRenameStatus(m_ParRenamer.GetStatus() == ParRenamer::psSuccess ? NZBInfo::rsSuccess : NZBInfo::rsFailure);
|
||||
pPostInfo->SetWorking(false);
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
if (m_ParRenamer.GetStatus() == ParRenamer::psFinished ||
|
||||
m_ParRenamer.GetStatus() == ParRenamer::psFailed)
|
||||
{
|
||||
g_pDiskState->SaveDownloadQueue(pDownloadQueue);
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
PostInfo* pPostInfo = m_ParRenamer.GetPostInfo();
|
||||
pPostInfo->SetWorking(false);
|
||||
if (pPostInfo->GetDeleted())
|
||||
{
|
||||
pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
}
|
||||
|
||||
// Update ParStatus by NZBInfo
|
||||
if (m_ParRenamer.GetStatus() == ParRenamer::psFailed && !m_ParRenamer.GetCancelled())
|
||||
{
|
||||
pPostInfo->SetRenameStatus(PostInfo::rsFailure);
|
||||
pPostInfo->GetNZBInfo()->SetRenameStatus(NZBInfo::rsFailure);
|
||||
}
|
||||
else if (m_ParRenamer.GetStatus() == ParRenamer::psFinished)
|
||||
{
|
||||
pPostInfo->SetRenameStatus(PostInfo::rsSuccess);
|
||||
pPostInfo->GetNZBInfo()->SetRenameStatus(NZBInfo::rsSuccess);
|
||||
}
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->SaveDownloadQueue(pDownloadQueue);
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
}
|
||||
|
||||
void ParCoordinator::UpdateParRenameProgress()
|
||||
{
|
||||
g_pQueueCoordinator->LockQueue();
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
PostInfo* pPostInfo = m_ParRenamer.GetPostInfo();
|
||||
PostInfo* pPostInfo = pDownloadQueue->GetPostQueue()->front();
|
||||
pPostInfo->SetProgressLabel(m_ParRenamer.GetProgressLabel());
|
||||
pPostInfo->SetStageProgress(m_ParRenamer.GetStageProgress());
|
||||
time_t tCurrent = time(NULL);
|
||||
@@ -688,39 +765,4 @@ void ParCoordinator::UpdateParRenameProgress()
|
||||
CheckPauseState(pPostInfo);
|
||||
}
|
||||
|
||||
void ParCoordinator::PrintMessage(PostInfo* pPostInfo, Message::EKind eKind, const char* szFormat, ...)
|
||||
{
|
||||
char szText[1024];
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
vsnprintf(szText, 1024, szFormat, args);
|
||||
va_end(args);
|
||||
szText[1024-1] = '\0';
|
||||
|
||||
pPostInfo->AppendMessage(eKind, szText);
|
||||
|
||||
switch (eKind)
|
||||
{
|
||||
case Message::mkDetail:
|
||||
detail("%s", szText);
|
||||
break;
|
||||
|
||||
case Message::mkInfo:
|
||||
info("%s", szText);
|
||||
break;
|
||||
|
||||
case Message::mkWarning:
|
||||
warn("%s", szText);
|
||||
break;
|
||||
|
||||
case Message::mkError:
|
||||
error("%s", szText);
|
||||
break;
|
||||
|
||||
case Message::mkDebug:
|
||||
debug("%s", szText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
#include "Observer.h"
|
||||
#include "DownloadInfo.h"
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
@@ -40,6 +41,13 @@ class ParCoordinator
|
||||
{
|
||||
private:
|
||||
#ifndef DISABLE_PARCHECK
|
||||
class ParCheckerObserver: public Observer
|
||||
{
|
||||
public:
|
||||
ParCoordinator* m_pOwner;
|
||||
virtual void Update(Subject* Caller, void* Aspect) { m_pOwner->ParCheckerUpdate(Caller, Aspect); }
|
||||
};
|
||||
|
||||
class PostParChecker: public ParChecker
|
||||
{
|
||||
private:
|
||||
@@ -48,8 +56,6 @@ private:
|
||||
protected:
|
||||
virtual bool RequestMorePars(int iBlockNeeded, int* pBlockFound);
|
||||
virtual void UpdateProgress();
|
||||
virtual void Completed() { m_pOwner->ParCheckCompleted(); }
|
||||
virtual void PrintMessage(Message::EKind eKind, const char* szFormat, ...);
|
||||
public:
|
||||
PostInfo* GetPostInfo() { return m_pPostInfo; }
|
||||
void SetPostInfo(PostInfo* pPostInfo) { m_pPostInfo = pPostInfo; }
|
||||
@@ -57,6 +63,13 @@ private:
|
||||
friend class ParCoordinator;
|
||||
};
|
||||
|
||||
class ParRenamerObserver: public Observer
|
||||
{
|
||||
public:
|
||||
ParCoordinator* m_pOwner;
|
||||
virtual void Update(Subject* Caller, void* Aspect) { m_pOwner->ParRenamerUpdate(Caller, Aspect); }
|
||||
};
|
||||
|
||||
class PostParRenamer: public ParRenamer
|
||||
{
|
||||
private:
|
||||
@@ -64,8 +77,6 @@ private:
|
||||
PostInfo* m_pPostInfo;
|
||||
protected:
|
||||
virtual void UpdateProgress();
|
||||
virtual void Completed() { m_pOwner->ParRenameCompleted(); }
|
||||
virtual void PrintMessage(Message::EKind eKind, const char* szFormat, ...);
|
||||
public:
|
||||
PostInfo* GetPostInfo() { return m_pPostInfo; }
|
||||
void SetPostInfo(PostInfo* pPostInfo) { m_pPostInfo = pPostInfo; }
|
||||
@@ -89,20 +100,16 @@ private:
|
||||
|
||||
private:
|
||||
PostParChecker m_ParChecker;
|
||||
ParCheckerObserver m_ParCheckerObserver;
|
||||
bool m_bStopped;
|
||||
bool m_bPostScript;
|
||||
PostParRenamer m_ParRenamer;
|
||||
ParRenamerObserver m_ParRenamerObserver;
|
||||
EJobKind m_eCurrentJob;
|
||||
|
||||
protected:
|
||||
virtual bool PauseDownload() = 0;
|
||||
virtual bool UnpauseDownload() = 0;
|
||||
void UpdateParCheckProgress();
|
||||
void UpdateParRenameProgress();
|
||||
void ParCheckCompleted();
|
||||
void ParRenameCompleted();
|
||||
void CheckPauseState(PostInfo* pPostInfo);
|
||||
bool RequestMorePars(NZBInfo* pNZBInfo, const char* szParFilename, int iBlockNeeded, int* pBlockFound);
|
||||
void PrintMessage(PostInfo* pPostInfo, Message::EKind eKind, const char* szFormat, ...);
|
||||
#endif
|
||||
|
||||
public:
|
||||
@@ -117,9 +124,15 @@ public:
|
||||
void PausePars(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
void ParCheckerUpdate(Subject* Caller, void* Aspect);
|
||||
void ParRenamerUpdate(Subject* Caller, void* Aspect);
|
||||
void CheckPauseState(PostInfo* pPostInfo);
|
||||
bool AddPar(FileInfo* pFileInfo, bool bDeleted);
|
||||
bool RequestMorePars(NZBInfo* pNZBInfo, const char* szParFilename, int iBlockNeeded, int* pBlockFound);
|
||||
void FindPars(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo, const char* szParFilename,
|
||||
Blocks* pBlocks, bool bStrictParName, bool bExactParName, int* pBlockFound);
|
||||
void UpdateParCheckProgress();
|
||||
void UpdateParRenameProgress();
|
||||
void StartParCheckJob(PostInfo* pPostInfo);
|
||||
void StartParRenameJob(PostInfo* pPostInfo);
|
||||
void Stop();
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <par2cmdline.h>
|
||||
#include <par2repairer.h>
|
||||
@@ -79,7 +79,7 @@ ParRenamer::ParRenamer()
|
||||
{
|
||||
debug("Creating ParRenamer");
|
||||
|
||||
m_eStatus = psFailed;
|
||||
m_eStatus = psUnknown;
|
||||
m_szDestDir = NULL;
|
||||
m_szInfoName = NULL;
|
||||
m_szProgressLabel = (char*)malloc(1024);
|
||||
@@ -131,6 +131,12 @@ void ParRenamer::SetInfoName(const char * szInfoName)
|
||||
m_szInfoName = strdup(szInfoName);
|
||||
}
|
||||
|
||||
void ParRenamer::SetStatus(EStatus eStatus)
|
||||
{
|
||||
m_eStatus = eStatus;
|
||||
Notify(NULL);
|
||||
}
|
||||
|
||||
void ParRenamer::Cancel()
|
||||
{
|
||||
m_bCancelled = true;
|
||||
@@ -141,7 +147,8 @@ void ParRenamer::Run()
|
||||
Cleanup();
|
||||
m_bCancelled = false;
|
||||
m_iRenamedCount = 0;
|
||||
m_eStatus = psFailed;
|
||||
|
||||
SetStatus(psUnknown);
|
||||
|
||||
snprintf(m_szProgressLabel, 1024, "Checking renamed files for %s", m_szInfoName);
|
||||
m_szProgressLabel[1024-1] = '\0';
|
||||
@@ -153,20 +160,21 @@ void ParRenamer::Run()
|
||||
|
||||
if (m_bCancelled)
|
||||
{
|
||||
PrintMessage(Message::mkWarning, "Renaming cancelled for %s", m_szInfoName);
|
||||
warn("Renaming cancelled for %s", m_szInfoName);
|
||||
SetStatus(psFailed);
|
||||
}
|
||||
else if (m_iRenamedCount > 0)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Successfully renamed %i file(s) for %s", m_iRenamedCount, m_szInfoName);
|
||||
m_eStatus = psSuccess;
|
||||
info("Successfully renamed %i file(s) for %s", m_iRenamedCount, m_szInfoName);
|
||||
SetStatus(psFinished);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "No renamed files found for %s", m_szInfoName);
|
||||
info("Could not rename any files for %s", m_szInfoName);
|
||||
SetStatus(psFailed);
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
Completed();
|
||||
}
|
||||
|
||||
void ParRenamer::LoadParFiles()
|
||||
@@ -194,7 +202,7 @@ void ParRenamer::LoadParFile(const char* szParFilename)
|
||||
|
||||
if (!pRepairer->LoadPacketsFromFile(szParFilename))
|
||||
{
|
||||
PrintMessage(Message::mkWarning, "Could not load par2-file %s", szParFilename);
|
||||
warn("Could not load par2-file %s", szParFilename);
|
||||
delete pRepairer;
|
||||
return;
|
||||
}
|
||||
@@ -256,7 +264,7 @@ void ParRenamer::CheckFile(const char* szFilename)
|
||||
FILE* pFile = fopen(szFilename, "rb");
|
||||
if (!pFile)
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not open file %s", szFilename);
|
||||
error("Could not open file %s", szFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -268,7 +276,7 @@ void ParRenamer::CheckFile(const char* szFilename)
|
||||
int iError = ferror(pFile);
|
||||
if (iReadBytes != iBlockSize && iError)
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not read file %s", szFilename);
|
||||
error("Could not read file %s", szFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -296,14 +304,14 @@ void ParRenamer::CheckFile(const char* szFilename)
|
||||
|
||||
if (!Util::FileExists(szDstFilename))
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Renaming %s to %s", Util::BaseFileName(szFilename), pFileHash->GetFilename());
|
||||
info("Renaming %s to %s", Util::BaseFileName(szFilename), pFileHash->GetFilename());
|
||||
if (Util::MoveFile(szFilename, szDstFilename))
|
||||
{
|
||||
m_iRenamedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not rename %s to %s", szFilename, szDstFilename);
|
||||
error("Could not rename %s to %s", szFilename, szDstFilename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,15 +31,16 @@
|
||||
#include <deque>
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Log.h"
|
||||
#include "Observer.h"
|
||||
|
||||
class ParRenamer : public Thread
|
||||
class ParRenamer : public Thread, public Subject
|
||||
{
|
||||
public:
|
||||
enum EStatus
|
||||
{
|
||||
psUnknown,
|
||||
psFailed,
|
||||
psSuccess
|
||||
psFinished
|
||||
};
|
||||
|
||||
class FileHash
|
||||
@@ -75,8 +76,6 @@ private:
|
||||
|
||||
protected:
|
||||
virtual void UpdateProgress() {}
|
||||
virtual void Completed() {}
|
||||
virtual void PrintMessage(Message::EKind eKind, const char* szFormat, ...) {}
|
||||
const char* GetProgressLabel() { return m_szProgressLabel; }
|
||||
int GetStageProgress() { return m_iStageProgress; }
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
@@ -49,15 +49,12 @@
|
||||
#include "DiskState.h"
|
||||
#include "Util.h"
|
||||
#include "Scheduler.h"
|
||||
#include "Scanner.h"
|
||||
#include "Unpack.h"
|
||||
#include "NZBFile.h"
|
||||
|
||||
extern QueueCoordinator* g_pQueueCoordinator;
|
||||
extern Options* g_pOptions;
|
||||
extern DiskState* g_pDiskState;
|
||||
extern Scheduler* g_pScheduler;
|
||||
extern Scanner* g_pScanner;
|
||||
|
||||
PrePostProcessor::PrePostProcessor()
|
||||
{
|
||||
@@ -69,6 +66,9 @@ PrePostProcessor::PrePostProcessor()
|
||||
m_QueueCoordinatorObserver.m_pOwner = this;
|
||||
g_pQueueCoordinator->Attach(&m_QueueCoordinatorObserver);
|
||||
|
||||
const char* szPostScript = g_pOptions->GetPostProcess();
|
||||
m_bPostScript = szPostScript && strlen(szPostScript) > 0;
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
m_ParCoordinator.m_pOwner = this;
|
||||
#endif
|
||||
@@ -125,11 +125,12 @@ void PrePostProcessor::Run()
|
||||
int iSchedulerInterval = 1000;
|
||||
int iHistoryInterval = 60000;
|
||||
const int iStepMSec = 200;
|
||||
m_Scanner.SetStepInterval(iStepMSec);
|
||||
|
||||
while (!IsStopped())
|
||||
{
|
||||
// check incoming nzb directory
|
||||
g_pScanner->Check();
|
||||
m_Scanner.Check();
|
||||
|
||||
if (!(g_pOptions->GetPauseDownload() || g_pOptions->GetPauseDownload2()) &&
|
||||
g_pOptions->GetDiskSpace() > 0 && !g_pQueueCoordinator->GetStandBy() &&
|
||||
@@ -215,19 +216,17 @@ void PrePostProcessor::QueueCoordinatorUpdate(Subject * Caller, void * Aspect)
|
||||
#ifndef DISABLE_PARCHECK
|
||||
!m_ParCoordinator.AddPar(pAspect->pFileInfo, pAspect->eAction == QueueCoordinator::eaFileDeleted) &&
|
||||
#endif
|
||||
IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, true, false) &&
|
||||
(!pAspect->pFileInfo->GetPaused() || IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, false, false)))
|
||||
IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, true, false, false) &&
|
||||
(!pAspect->pFileInfo->GetPaused() || IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, false, false, false)))
|
||||
{
|
||||
if (pAspect->eAction == QueueCoordinator::eaFileCompleted ||
|
||||
(pAspect->pFileInfo->GetAutoDeleted() &&
|
||||
IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, false, true)))
|
||||
if (pAspect->eAction == QueueCoordinator::eaFileCompleted)
|
||||
{
|
||||
info("Collection %s completely downloaded", pAspect->pNZBInfo->GetName());
|
||||
NZBDownloaded(pAspect->pDownloadQueue, pAspect->pNZBInfo);
|
||||
}
|
||||
else if (pAspect->eAction == QueueCoordinator::eaFileDeleted &&
|
||||
else if (pAspect->pNZBInfo->GetDeleted() &&
|
||||
!pAspect->pNZBInfo->GetParCleanup() &&
|
||||
IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, false, true))
|
||||
IsNZBFileCompleted(pAspect->pDownloadQueue, pAspect->pNZBInfo, false, false, true))
|
||||
{
|
||||
info("Collection %s deleted from queue", pAspect->pNZBInfo->GetName());
|
||||
NZBDeleted(pAspect->pDownloadQueue, pAspect->pNZBInfo);
|
||||
@@ -238,14 +237,12 @@ void PrePostProcessor::QueueCoordinatorUpdate(Subject * Caller, void * Aspect)
|
||||
|
||||
void PrePostProcessor::NZBAdded(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo)
|
||||
{
|
||||
PostScriptController::InitParamsForNewNZB(pNZBInfo);
|
||||
|
||||
if (g_pOptions->GetMergeNzb())
|
||||
{
|
||||
pNZBInfo = MergeGroups(pDownloadQueue, pNZBInfo);
|
||||
}
|
||||
|
||||
if (g_pOptions->GetParCheck() != Options::pcForce)
|
||||
if (g_pOptions->GetLoadPars() != Options::lpAll)
|
||||
{
|
||||
m_ParCoordinator.PausePars(pDownloadQueue, pNZBInfo);
|
||||
}
|
||||
@@ -258,30 +255,24 @@ void PrePostProcessor::NZBAdded(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo
|
||||
|
||||
void PrePostProcessor::NZBDownloaded(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo)
|
||||
{
|
||||
if (!pNZBInfo->GetPostProcess() && g_pOptions->GetDecode())
|
||||
bool bPostProcessed = false;
|
||||
|
||||
if (!pNZBInfo->GetPostProcess() || (m_bPostScript && g_pOptions->GetAllowReProcess()))
|
||||
{
|
||||
info("Queueing %s for post-processing", pNZBInfo->GetName());
|
||||
|
||||
PostInfo* pPostInfo = new PostInfo();
|
||||
pPostInfo->SetNZBInfo(pNZBInfo);
|
||||
pPostInfo->SetInfoName(pNZBInfo->GetName());
|
||||
|
||||
if (pNZBInfo->GetParStatus() == NZBInfo::psNone && g_pOptions->GetParCheck() != Options::pcForce)
|
||||
#ifdef DISABLE_PARCHECK
|
||||
bool bParCheck = false;
|
||||
#else
|
||||
bool bParCheck = g_pOptions->GetParCheck() && g_pOptions->GetDecode();
|
||||
#endif
|
||||
if ((bParCheck || m_bPostScript || g_pOptions->GetUnpack() || strlen(g_pOptions->GetInterDir()) > 0) &&
|
||||
CreatePostJobs(pDownloadQueue, pNZBInfo, bParCheck, true, false))
|
||||
{
|
||||
pNZBInfo->SetParStatus(NZBInfo::psSkipped);
|
||||
pNZBInfo->SetPostProcess(true);
|
||||
bPostProcessed = true;
|
||||
}
|
||||
|
||||
if (pNZBInfo->GetRenameStatus() == NZBInfo::rsNone)
|
||||
{
|
||||
pNZBInfo->SetRenameStatus(NZBInfo::rsSkipped);
|
||||
}
|
||||
|
||||
pNZBInfo->SetPostProcess(true);
|
||||
pDownloadQueue->GetPostQueue()->push_back(pPostInfo);
|
||||
SaveQueue(pDownloadQueue);
|
||||
m_bHasMoreJobs = true;
|
||||
}
|
||||
else
|
||||
|
||||
if (!bPostProcessed)
|
||||
{
|
||||
NZBCompleted(pDownloadQueue, pNZBInfo, true);
|
||||
}
|
||||
@@ -297,33 +288,15 @@ void PrePostProcessor::NZBDeleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBIn
|
||||
char* szFilename = *it;
|
||||
if (Util::FileExists(szFilename))
|
||||
{
|
||||
detail("Deleting file %s", Util::BaseFileName(szFilename));
|
||||
remove(szFilename);
|
||||
}
|
||||
}
|
||||
|
||||
// delete .out.tmp-files and _brokenlog.txt
|
||||
DirBrowser dir(pNZBInfo->GetDestDir());
|
||||
while (const char* szFilename = dir.Next())
|
||||
{
|
||||
int iLen = strlen(szFilename);
|
||||
if ((iLen > 8 && !strcmp(szFilename + iLen - 8, ".out.tmp")) || !strcmp(szFilename, "_brokenlog.txt"))
|
||||
{
|
||||
char szFullFilename[1024];
|
||||
snprintf(szFullFilename, 1024, "%s%c%s", pNZBInfo->GetDestDir(), PATH_SEPARATOR, szFilename);
|
||||
szFullFilename[1024-1] = '\0';
|
||||
|
||||
detail("Deleting file %s", szFilename);
|
||||
remove(szFullFilename);
|
||||
remove(szFilename);
|
||||
// delete old directory (if empty)
|
||||
if (g_pOptions->GetAppendNZBDir() && Util::DirEmpty(pNZBInfo->GetDestDir()))
|
||||
{
|
||||
rmdir(pNZBInfo->GetDestDir());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete old directory (if empty)
|
||||
if (Util::DirEmpty(pNZBInfo->GetDestDir()))
|
||||
{
|
||||
rmdir(pNZBInfo->GetDestDir());
|
||||
}
|
||||
|
||||
if (g_pOptions->GetNzbCleanupDisk())
|
||||
{
|
||||
DeleteQueuedFile(pNZBInfo->GetQueuedFilename());
|
||||
@@ -489,6 +462,11 @@ NZBInfo* PrePostProcessor::MergeGroups(DownloadQueue* pDownloadQueue, NZBInfo* p
|
||||
return pNZBInfo;
|
||||
}
|
||||
|
||||
void PrePostProcessor::ScanNZBDir(bool bSyncMode)
|
||||
{
|
||||
m_Scanner.ScanNZBDir(bSyncMode);
|
||||
}
|
||||
|
||||
void PrePostProcessor::CheckDiskSpace()
|
||||
{
|
||||
long long lFreeSpace = Util::FreeDiskSize(g_pOptions->GetDestDir());
|
||||
@@ -509,54 +487,44 @@ void PrePostProcessor::CheckPostQueue()
|
||||
if (!pPostInfo->GetWorking())
|
||||
{
|
||||
#ifndef DISABLE_PARCHECK
|
||||
if (pPostInfo->GetRequestParCheck() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped &&
|
||||
g_pOptions->GetParCheck() != Options::pcManual)
|
||||
if (pPostInfo->GetRequestParCheck() == PostInfo::rpAll)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psNone);
|
||||
pPostInfo->SetRequestParCheck(false);
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
pPostInfo->GetNZBInfo()->GetScriptStatuses()->Clear();
|
||||
DeletePostThread(pPostInfo);
|
||||
if (!CreatePostJobs(pDownloadQueue, pPostInfo->GetNZBInfo(), true, false, true))
|
||||
{
|
||||
error("Could not par-check %s: there are no par-files", pPostInfo->GetNZBInfo()->GetName());
|
||||
}
|
||||
}
|
||||
else if (pPostInfo->GetRequestParCheck() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped &&
|
||||
g_pOptions->GetParCheck() == Options::pcManual)
|
||||
else if (pPostInfo->GetRequestParCheck() == PostInfo::rpCurrent && pPostInfo->GetParStatus() <= PostInfo::psSkipped)
|
||||
{
|
||||
pPostInfo->SetRequestParCheck(false);
|
||||
pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psManual);
|
||||
pPostInfo->SetParStatus(PostInfo::psNone);
|
||||
pPostInfo->SetRequestParCheck(PostInfo::rpNone);
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
DeletePostThread(pPostInfo);
|
||||
|
||||
FileInfo* pFileInfo = GetQueueGroup(pDownloadQueue, pPostInfo->GetNZBInfo());
|
||||
if (pFileInfo)
|
||||
{
|
||||
info("Downloading all remaining files for manual par-check for %s", pPostInfo->GetNZBInfo()->GetName());
|
||||
g_pQueueCoordinator->GetQueueEditor()->LockedEditEntry(pDownloadQueue, pFileInfo->GetID(), false, QueueEditor::eaGroupResume, 0, NULL);
|
||||
pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
pPostInfo->GetNZBInfo()->SetPostProcess(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
info("There are no par-files remain for download for %s", pPostInfo->GetNZBInfo()->GetName());
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
}
|
||||
}
|
||||
else if (pPostInfo->GetRequestParRename())
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetRenameStatus(NZBInfo::rsNone);
|
||||
pPostInfo->SetRenameStatus(PostInfo::rsNone);
|
||||
pPostInfo->SetRequestParRename(false);
|
||||
pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
DeletePostThread(pPostInfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (pPostInfo->GetDeleted())
|
||||
if (pPostInfo->GetStage() == PostInfo::ptQueued && pPostInfo->GetRenameStatus() == PostInfo::rsNone && !g_pOptions->GetPausePostProcess())
|
||||
{
|
||||
pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
UpdatePauseState(g_pOptions->GetParPauseQueue(), "par-rename");
|
||||
m_ParCoordinator.StartParRenameJob(pPostInfo);
|
||||
}
|
||||
|
||||
else if (pPostInfo->GetStage() == PostInfo::ptQueued && pPostInfo->GetParStatus() == PostInfo::psNone && !g_pOptions->GetPausePostProcess())
|
||||
{
|
||||
UpdatePauseState(g_pOptions->GetParPauseQueue(), "par-check");
|
||||
m_ParCoordinator.StartParCheckJob(pPostInfo);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (pPostInfo->GetStage() == PostInfo::ptQueued && !g_pOptions->GetPausePostProcess())
|
||||
{
|
||||
DeletePostThread(pPostInfo);
|
||||
StartJob(pDownloadQueue, pPostInfo);
|
||||
StartProcessJob(pDownloadQueue, pPostInfo);
|
||||
}
|
||||
else if (pPostInfo->GetStage() == PostInfo::ptFinished)
|
||||
{
|
||||
@@ -611,75 +579,37 @@ void PrePostProcessor::DeletePostThread(PostInfo* pPostInfo)
|
||||
}
|
||||
}
|
||||
|
||||
void PrePostProcessor::StartJob(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo)
|
||||
void PrePostProcessor::StartProcessJob(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
|
||||
|
||||
bool bUnpack = g_pOptions->GetUnpack() && (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 &&
|
||||
bool bUnpack = g_pOptions->GetUnpack() && (pPostInfo->GetUnpackStatus() == PostInfo::usNone);
|
||||
bool bNZBFileCompleted = IsNZBFileCompleted(pDownloadQueue, pPostInfo->GetNZBInfo(), true, true, false);
|
||||
bool bHasFailedParJobs = pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psFailure ||
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psRepairPossible;
|
||||
bool bMoveInterToDest = !bUnpack &&
|
||||
pPostInfo->GetNZBInfo()->GetMoveStatus() == NZBInfo::msNone &&
|
||||
pPostInfo->GetNZBInfo()->GetUnpackStatus() != NZBInfo::usFailure &&
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure &&
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psManual &&
|
||||
pPostInfo->GetUnpackStatus() != PostInfo::usFailure &&
|
||||
pPostInfo->GetParStatus() != PostInfo::psFailure &&
|
||||
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)
|
||||
if (bUnpack && bHasFailedParJobs)
|
||||
{
|
||||
warn("Skipping unpack due to %s for %s",
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psManual ? "required par-repair" : "par-failure",
|
||||
pPostInfo->GetInfoName());
|
||||
warn("Skipping unpack due to par-failure for %s", pPostInfo->GetInfoName());
|
||||
pPostInfo->SetUnpackStatus(PostInfo::usSkipped);
|
||||
pPostInfo->GetNZBInfo()->SetUnpackStatus(NZBInfo::usSkipped);
|
||||
bUnpack = false;
|
||||
}
|
||||
|
||||
if (!bUnpack && !bMoveInter && !bPostScript)
|
||||
if ((!bNZBFileCompleted && !(m_bPostScript && g_pOptions->GetAllowReProcess())) ||
|
||||
(!bUnpack && !m_bPostScript && !bMoveInterToDest))
|
||||
{
|
||||
pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
return;
|
||||
}
|
||||
|
||||
pPostInfo->SetProgressLabel(bUnpack ? "Unpacking" : bMoveInter ? "Moving" : "Executing post-process-script");
|
||||
pPostInfo->SetProgressLabel(bUnpack ? "Unpacking" : bMoveInterToDest ? "Moving" : "Executing post-process-script");
|
||||
pPostInfo->SetWorking(true);
|
||||
pPostInfo->SetStage(bUnpack ? PostInfo::ptUnpacking : bMoveInter ? PostInfo::ptMoving : PostInfo::ptExecutingScript);
|
||||
pPostInfo->SetStage(bUnpack ? PostInfo::ptUnpacking : bMoveInterToDest ? PostInfo::ptMoving : PostInfo::ptExecutingScript);
|
||||
pPostInfo->SetFileProgress(0);
|
||||
pPostInfo->SetStageProgress(0);
|
||||
SaveQueue(pDownloadQueue);
|
||||
@@ -693,22 +623,17 @@ void PrePostProcessor::StartJob(DownloadQueue* pDownloadQueue, PostInfo* pPostIn
|
||||
if (bUnpack)
|
||||
{
|
||||
UpdatePauseState(g_pOptions->GetUnpackPauseQueue(), "unpack");
|
||||
UnpackController::StartJob(pPostInfo);
|
||||
UnpackController::StartUnpackJob(pPostInfo);
|
||||
}
|
||||
else if (bCleanup)
|
||||
else if (bMoveInterToDest)
|
||||
{
|
||||
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);
|
||||
UpdatePauseState(g_pOptions->GetUnpackPauseQueue() || g_pOptions->GetPostPauseQueue(), "move");
|
||||
MoveController::StartMoveJob(pPostInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdatePauseState(g_pOptions->GetScriptPauseQueue(), "post-process-script");
|
||||
PostScriptController::StartJob(pPostInfo);
|
||||
UpdatePauseState(g_pOptions->GetPostPauseQueue(), "post-process-script");
|
||||
PostScriptController::StartScriptJob(pPostInfo, bNZBFileCompleted, bHasFailedParJobs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,15 +645,31 @@ void PrePostProcessor::JobCompleted(DownloadQueue* pDownloadQueue, PostInfo* pPo
|
||||
|
||||
DeletePostThread(pPostInfo);
|
||||
|
||||
if (IsNZBFileCompleted(pDownloadQueue, pPostInfo->GetNZBInfo(), true, false))
|
||||
// Update ScriptStatus by NZBInfo (accumulate result)
|
||||
if (pPostInfo->GetScriptStatus() == PostInfo::srUnknown &&
|
||||
pPostInfo->GetNZBInfo()->GetScriptStatus() != NZBInfo::srFailure)
|
||||
{
|
||||
// Cleaning up queue if par-check was successful or unpack was successful or
|
||||
// script was successful (if unpack was not performed)
|
||||
pPostInfo->GetNZBInfo()->SetScriptStatus(NZBInfo::srUnknown);
|
||||
}
|
||||
else if (pPostInfo->GetScriptStatus() == PostInfo::srFailure)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetScriptStatus(NZBInfo::srFailure);
|
||||
}
|
||||
else if (pPostInfo->GetScriptStatus() == PostInfo::srSuccess &&
|
||||
pPostInfo->GetNZBInfo()->GetScriptStatus() == NZBInfo::srNone)
|
||||
{
|
||||
pPostInfo->GetNZBInfo()->SetScriptStatus(NZBInfo::srSuccess);
|
||||
}
|
||||
|
||||
if (IsNZBFileCompleted(pDownloadQueue, pPostInfo->GetNZBInfo(), true, true, false))
|
||||
{
|
||||
// Cleaning up queue if all par-checks were successful or all unpacks were successful or
|
||||
// all scripts were successful (if unpack was not performed)
|
||||
bool bCanCleanupQueue = pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psSuccess ||
|
||||
pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psRepairPossible ||
|
||||
pPostInfo->GetNZBInfo()->GetUnpackStatus() == NZBInfo::usSuccess ||
|
||||
(pPostInfo->GetNZBInfo()->GetUnpackStatus() == NZBInfo::usNone &&
|
||||
pPostInfo->GetNZBInfo()->GetScriptStatuses()->CalcTotalStatus() == ScriptStatus::srSuccess);
|
||||
pPostInfo->GetNZBInfo()->GetScriptStatus() == NZBInfo::srSuccess);
|
||||
if ((g_pOptions->GetParCleanupQueue() || g_pOptions->GetNzbCleanupDisk()) && bCanCleanupQueue)
|
||||
{
|
||||
if (g_pOptions->GetParCleanupQueue())
|
||||
@@ -768,7 +709,7 @@ void PrePostProcessor::JobCompleted(DownloadQueue* pDownloadQueue, PostInfo* pPo
|
||||
}
|
||||
|
||||
bool PrePostProcessor::IsNZBFileCompleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo,
|
||||
bool bIgnorePausedPars, bool bAllowOnlyOneDeleted)
|
||||
bool bIgnorePausedPars, bool bCheckPostQueue, bool bAllowOnlyOneDeleted)
|
||||
{
|
||||
bool bNZBFileCompleted = true;
|
||||
int iDeleted = 0;
|
||||
@@ -782,8 +723,11 @@ bool PrePostProcessor::IsNZBFileCompleted(DownloadQueue* pDownloadQueue, NZBInfo
|
||||
{
|
||||
iDeleted++;
|
||||
}
|
||||
// Special case if option "AllowReProcess" is active:
|
||||
// paused non-par-files are treated the same way as paused par-files,
|
||||
// meaning: the NZB considered completed even if there are paused non-par-files.
|
||||
if (((!pFileInfo->GetPaused() || !bIgnorePausedPars ||
|
||||
!(m_ParCoordinator.ParseParFilename(pFileInfo->GetFilename(), NULL, NULL))) &&
|
||||
!(m_ParCoordinator.ParseParFilename(pFileInfo->GetFilename(), NULL, NULL) || g_pOptions->GetAllowReProcess())) &&
|
||||
!pFileInfo->GetDeleted()) ||
|
||||
(bAllowOnlyOneDeleted && iDeleted > 1))
|
||||
{
|
||||
@@ -793,9 +737,116 @@ bool PrePostProcessor::IsNZBFileCompleted(DownloadQueue* pDownloadQueue, NZBInfo
|
||||
}
|
||||
}
|
||||
|
||||
if (bNZBFileCompleted && bCheckPostQueue)
|
||||
{
|
||||
for (PostQueue::iterator it = pDownloadQueue->GetPostQueue()->begin() + 1; it != pDownloadQueue->GetPostQueue()->end(); it++)
|
||||
{
|
||||
PostInfo* pPostInfo = *it;
|
||||
if (pPostInfo->GetNZBInfo() == pNZBInfo)
|
||||
{
|
||||
bNZBFileCompleted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bNZBFileCompleted;
|
||||
}
|
||||
|
||||
bool PrePostProcessor::CreatePostJobs(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo,
|
||||
bool bParCheck, bool bUnpackOrScript, bool bAddTop)
|
||||
{
|
||||
debug("Queueing post-process-jobs");
|
||||
|
||||
PostQueue cPostQueue;
|
||||
bool bJobsAdded = false;
|
||||
|
||||
ParCoordinator::FileList fileList;
|
||||
if (m_ParCoordinator.FindMainPars(pNZBInfo->GetDestDir(), &fileList))
|
||||
{
|
||||
debug("Found pars");
|
||||
|
||||
for (ParCoordinator::FileList::iterator it = fileList.begin(); it != fileList.end(); it++)
|
||||
{
|
||||
char* szParFilename = *it;
|
||||
debug("Found par: %s", szParFilename);
|
||||
|
||||
char szFullParFilename[1024];
|
||||
snprintf(szFullParFilename, 1024, "%s%c%s", pNZBInfo->GetDestDir(), (int)PATH_SEPARATOR, szParFilename);
|
||||
szFullParFilename[1024-1] = '\0';
|
||||
|
||||
char szInfoName[1024];
|
||||
int iBaseLen = 0;
|
||||
m_ParCoordinator.ParseParFilename(szParFilename, &iBaseLen, NULL);
|
||||
int maxlen = iBaseLen < 1024 ? iBaseLen : 1024 - 1;
|
||||
strncpy(szInfoName, szParFilename, maxlen);
|
||||
szInfoName[maxlen] = '\0';
|
||||
|
||||
char szParInfoName[1024];
|
||||
snprintf(szParInfoName, 1024, "%s%c%s", pNZBInfo->GetName(), (int)PATH_SEPARATOR, szInfoName);
|
||||
szParInfoName[1024-1] = '\0';
|
||||
|
||||
if (cPostQueue.empty())
|
||||
{
|
||||
info("Queueing %s for post-processing", pNZBInfo->GetName());
|
||||
}
|
||||
|
||||
PostInfo* pPostInfo = new PostInfo();
|
||||
pPostInfo->SetNZBInfo(pNZBInfo);
|
||||
pPostInfo->SetParFilename(szFullParFilename);
|
||||
pPostInfo->SetInfoName(szParInfoName);
|
||||
pPostInfo->SetRenameStatus(PostInfo::rsSkipped);
|
||||
pPostInfo->SetParStatus(bParCheck && !pNZBInfo->GetUnpackCleanedUpDisk() ? PostInfo::psNone : PostInfo::psSkipped);
|
||||
pPostInfo->SetUnpackStatus(!pNZBInfo->GetUnpackCleanedUpDisk() ? PostInfo::usNone : PostInfo::usSkipped);
|
||||
if (bAddTop)
|
||||
{
|
||||
cPostQueue.push_front(pPostInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
cPostQueue.push_back(pPostInfo);
|
||||
}
|
||||
bJobsAdded = true;
|
||||
|
||||
free(szParFilename);
|
||||
}
|
||||
}
|
||||
|
||||
if (cPostQueue.empty() && bUnpackOrScript && (m_bPostScript || g_pOptions->GetUnpack()))
|
||||
{
|
||||
info("Queueing %s for post-processing", pNZBInfo->GetName());
|
||||
PostInfo* pPostInfo = new PostInfo();
|
||||
pPostInfo->SetNZBInfo(pNZBInfo);
|
||||
pPostInfo->SetParFilename("");
|
||||
pPostInfo->SetInfoName(pNZBInfo->GetName());
|
||||
pPostInfo->SetRenameStatus(PostInfo::rsSkipped);
|
||||
pPostInfo->SetParStatus(PostInfo::psSkipped);
|
||||
pPostInfo->SetUnpackStatus(!pNZBInfo->GetUnpackCleanedUpDisk() ? PostInfo::usNone : PostInfo::usSkipped);
|
||||
cPostQueue.push_back(pPostInfo);
|
||||
bJobsAdded = true;
|
||||
}
|
||||
|
||||
for (PostQueue::iterator it = cPostQueue.begin(); it != cPostQueue.end(); it++)
|
||||
{
|
||||
if (bAddTop)
|
||||
{
|
||||
pDownloadQueue->GetPostQueue()->push_front(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
pDownloadQueue->GetPostQueue()->push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
if (bJobsAdded)
|
||||
{
|
||||
SaveQueue(pDownloadQueue);
|
||||
m_bHasMoreJobs = true;
|
||||
}
|
||||
|
||||
return bJobsAdded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first FileInfo belonging to given NZBInfo.
|
||||
*/
|
||||
@@ -901,7 +952,7 @@ void PrePostProcessor::CheckScheduledResume()
|
||||
}
|
||||
}
|
||||
|
||||
bool PrePostProcessor::QueueEditList(IDList* pIDList, EEditAction eAction, int iOffset, const char* szText)
|
||||
bool PrePostProcessor::QueueEditList(IDList* pIDList, EEditAction eAction, int iOffset)
|
||||
{
|
||||
debug("Edit-command for post-processor received");
|
||||
switch (eAction)
|
||||
@@ -915,10 +966,11 @@ bool PrePostProcessor::QueueEditList(IDList* pIDList, EEditAction eAction, int i
|
||||
return PostQueueDelete(pIDList);
|
||||
|
||||
case eaHistoryDelete:
|
||||
return HistoryDelete(pIDList);
|
||||
|
||||
case eaHistoryReturn:
|
||||
case eaHistoryProcess:
|
||||
case eaHistorySetParameter:
|
||||
return HistoryEdit(pIDList, eAction, iOffset, szText);
|
||||
return HistoryReturn(pIDList, eAction == eaHistoryProcess);
|
||||
|
||||
default:
|
||||
return false;
|
||||
@@ -1052,7 +1104,7 @@ bool PrePostProcessor::PostQueueMove(IDList* pIDList, EEditAction eAction, int i
|
||||
return bOK;
|
||||
}
|
||||
|
||||
bool PrePostProcessor::HistoryEdit(IDList* pIDList, EEditAction eAction, int iOffset, const char* szText)
|
||||
bool PrePostProcessor::HistoryDelete(IDList* pIDList)
|
||||
{
|
||||
bool bOK = false;
|
||||
|
||||
@@ -1066,26 +1118,39 @@ bool PrePostProcessor::HistoryEdit(IDList* pIDList, EEditAction eAction, int iOf
|
||||
HistoryInfo* pHistoryInfo = *itHistory;
|
||||
if (pHistoryInfo->GetID() == iID)
|
||||
{
|
||||
switch (eAction)
|
||||
char szNiceName[1024];
|
||||
pHistoryInfo->GetName(szNiceName, 1024);
|
||||
info("Deleting %s from history", szNiceName);
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkNZBInfo)
|
||||
{
|
||||
case eaHistoryDelete:
|
||||
HistoryDelete(pDownloadQueue, itHistory, pHistoryInfo);
|
||||
break;
|
||||
NZBInfo* pNZBInfo = pHistoryInfo->GetNZBInfo();
|
||||
|
||||
case eaHistoryReturn:
|
||||
case eaHistoryProcess:
|
||||
HistoryReturn(pDownloadQueue, itHistory, pHistoryInfo, eAction == eaHistoryProcess);
|
||||
break;
|
||||
|
||||
case eaHistorySetParameter:
|
||||
HistorySetParameter(pHistoryInfo, szText);
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing, just to avoid compiler warning
|
||||
break;
|
||||
// delete parked files
|
||||
int index = 0;
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetParkedFiles()->begin(); it != pDownloadQueue->GetParkedFiles()->end(); )
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetNZBInfo() == pNZBInfo)
|
||||
{
|
||||
pDownloadQueue->GetParkedFiles()->erase(it);
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->DiscardFile(pFileInfo);
|
||||
}
|
||||
delete pFileInfo;
|
||||
it = pDownloadQueue->GetParkedFiles()->begin() + index;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pDownloadQueue->GetHistoryList()->erase(itHistory);
|
||||
delete pHistoryInfo;
|
||||
bOK = true;
|
||||
break;
|
||||
}
|
||||
@@ -1102,152 +1167,112 @@ bool PrePostProcessor::HistoryEdit(IDList* pIDList, EEditAction eAction, int iOf
|
||||
return bOK;
|
||||
}
|
||||
|
||||
void PrePostProcessor::HistoryDelete(DownloadQueue* pDownloadQueue, HistoryList::iterator itHistory, HistoryInfo* pHistoryInfo)
|
||||
bool PrePostProcessor::HistoryReturn(IDList* pIDList, bool bReprocess)
|
||||
{
|
||||
char szNiceName[1024];
|
||||
pHistoryInfo->GetName(szNiceName, 1024);
|
||||
info("Deleting %s from history", szNiceName);
|
||||
bool bOK = false;
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkNZBInfo)
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
for (IDList::iterator itID = pIDList->begin(); itID != pIDList->end(); itID++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = pHistoryInfo->GetNZBInfo();
|
||||
|
||||
// delete parked files
|
||||
int index = 0;
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetParkedFiles()->begin(); it != pDownloadQueue->GetParkedFiles()->end(); )
|
||||
int iID = *itID;
|
||||
for (HistoryList::iterator itHistory = pDownloadQueue->GetHistoryList()->begin(); itHistory != pDownloadQueue->GetHistoryList()->end(); itHistory++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetNZBInfo() == pNZBInfo)
|
||||
HistoryInfo* pHistoryInfo = *itHistory;
|
||||
if (pHistoryInfo->GetID() == iID)
|
||||
{
|
||||
pDownloadQueue->GetParkedFiles()->erase(it);
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
char szNiceName[1024];
|
||||
pHistoryInfo->GetName(szNiceName, 1024);
|
||||
debug("Returning %s from history back to download queue", szNiceName);
|
||||
bool bUnparked = false;
|
||||
|
||||
if (bReprocess && pHistoryInfo->GetKind() != HistoryInfo::hkNZBInfo)
|
||||
{
|
||||
g_pDiskState->DiscardFile(pFileInfo);
|
||||
error("Could not restart postprocessing for %s: history item has wrong type", szNiceName);
|
||||
break;
|
||||
}
|
||||
delete pFileInfo;
|
||||
it = pDownloadQueue->GetParkedFiles()->begin() + index;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
index++;
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkNZBInfo)
|
||||
{
|
||||
NZBInfo* pNZBInfo = pHistoryInfo->GetNZBInfo();
|
||||
|
||||
// unpark files
|
||||
int index = 0;
|
||||
for (FileQueue::reverse_iterator it = pDownloadQueue->GetParkedFiles()->rbegin(); it != pDownloadQueue->GetParkedFiles()->rend(); )
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetNZBInfo() == pNZBInfo)
|
||||
{
|
||||
detail("Unpark file %s", pFileInfo->GetFilename());
|
||||
pDownloadQueue->GetParkedFiles()->erase(pDownloadQueue->GetParkedFiles()->end() - 1 - index);
|
||||
pDownloadQueue->GetFileQueue()->push_front(pFileInfo);
|
||||
bUnparked = true;
|
||||
it = pDownloadQueue->GetParkedFiles()->rbegin() + index;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// reset postprocessing status variables
|
||||
pNZBInfo->SetPostProcess(false);
|
||||
pNZBInfo->SetParCleanup(false);
|
||||
if (!pNZBInfo->GetUnpackCleanedUpDisk())
|
||||
{
|
||||
pNZBInfo->SetParStatus(NZBInfo::psNone);
|
||||
pNZBInfo->SetRenameStatus(NZBInfo::rsNone);
|
||||
pNZBInfo->SetUnpackStatus(NZBInfo::usNone);
|
||||
}
|
||||
pNZBInfo->SetScriptStatus(NZBInfo::srNone);
|
||||
pNZBInfo->SetParkedFileCount(0);
|
||||
}
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkUrlInfo)
|
||||
{
|
||||
UrlInfo* pUrlInfo = pHistoryInfo->GetUrlInfo();
|
||||
pHistoryInfo->DiscardUrlInfo();
|
||||
pUrlInfo->SetStatus(UrlInfo::aiUndefined);
|
||||
pDownloadQueue->GetUrlQueue()->push_back(pUrlInfo);
|
||||
bUnparked = true;
|
||||
}
|
||||
|
||||
if (bUnparked || bReprocess)
|
||||
{
|
||||
pDownloadQueue->GetHistoryList()->erase(itHistory);
|
||||
// the object "pHistoryInfo" is released few lines later, after the call to "NZBDownloaded"
|
||||
info("%s returned from history back to download queue", szNiceName);
|
||||
bOK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
warn("Could not return %s back from history to download queue: history item does not have any files left for download", szNiceName);
|
||||
}
|
||||
|
||||
if (bReprocess)
|
||||
{
|
||||
// start postprocessing
|
||||
debug("Restarting postprocessing for %s", szNiceName);
|
||||
NZBDownloaded(pDownloadQueue, pHistoryInfo->GetNZBInfo());
|
||||
}
|
||||
|
||||
if (bUnparked || bReprocess)
|
||||
{
|
||||
delete pHistoryInfo;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pDownloadQueue->GetHistoryList()->erase(itHistory);
|
||||
delete pHistoryInfo;
|
||||
}
|
||||
|
||||
void PrePostProcessor::HistoryReturn(DownloadQueue* pDownloadQueue, HistoryList::iterator itHistory, HistoryInfo* pHistoryInfo, bool bReprocess)
|
||||
{
|
||||
char szNiceName[1024];
|
||||
pHistoryInfo->GetName(szNiceName, 1024);
|
||||
debug("Returning %s from history back to download queue", szNiceName);
|
||||
bool bUnparked = false;
|
||||
|
||||
if (bReprocess && pHistoryInfo->GetKind() != HistoryInfo::hkNZBInfo)
|
||||
{
|
||||
error("Could not restart postprocessing for %s: history item has wrong type", szNiceName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkNZBInfo)
|
||||
{
|
||||
NZBInfo* pNZBInfo = pHistoryInfo->GetNZBInfo();
|
||||
|
||||
// unpark files
|
||||
int index = 0;
|
||||
for (FileQueue::reverse_iterator it = pDownloadQueue->GetParkedFiles()->rbegin(); it != pDownloadQueue->GetParkedFiles()->rend(); )
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetNZBInfo() == pNZBInfo)
|
||||
{
|
||||
detail("Unpark file %s", pFileInfo->GetFilename());
|
||||
pDownloadQueue->GetParkedFiles()->erase(pDownloadQueue->GetParkedFiles()->end() - 1 - index);
|
||||
pDownloadQueue->GetFileQueue()->push_front(pFileInfo);
|
||||
bUnparked = true;
|
||||
it = pDownloadQueue->GetParkedFiles()->rbegin() + index;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// reset postprocessing status variables
|
||||
pNZBInfo->SetPostProcess(false);
|
||||
pNZBInfo->SetParCleanup(false);
|
||||
if (!pNZBInfo->GetUnpackCleanedUpDisk())
|
||||
{
|
||||
pNZBInfo->SetParStatus(NZBInfo::psNone);
|
||||
pNZBInfo->SetRenameStatus(NZBInfo::rsNone);
|
||||
pNZBInfo->SetUnpackStatus(NZBInfo::usNone);
|
||||
pNZBInfo->SetCleanupStatus(NZBInfo::csNone);
|
||||
}
|
||||
pNZBInfo->GetScriptStatuses()->Clear();
|
||||
pNZBInfo->SetParkedFileCount(0);
|
||||
}
|
||||
|
||||
if (pHistoryInfo->GetKind() == HistoryInfo::hkUrlInfo)
|
||||
{
|
||||
UrlInfo* pUrlInfo = pHistoryInfo->GetUrlInfo();
|
||||
pHistoryInfo->DiscardUrlInfo();
|
||||
pUrlInfo->SetStatus(UrlInfo::aiUndefined);
|
||||
pDownloadQueue->GetUrlQueue()->push_back(pUrlInfo);
|
||||
bUnparked = true;
|
||||
}
|
||||
|
||||
if (bUnparked || bReprocess)
|
||||
{
|
||||
pDownloadQueue->GetHistoryList()->erase(itHistory);
|
||||
// the object "pHistoryInfo" is released few lines later, after the call to "NZBDownloaded"
|
||||
info("%s returned from history back to download queue", szNiceName);
|
||||
}
|
||||
else
|
||||
{
|
||||
warn("Could not return %s back from history to download queue: history item does not have any files left for download", szNiceName);
|
||||
}
|
||||
|
||||
if (bReprocess)
|
||||
{
|
||||
// start postprocessing
|
||||
debug("Restarting postprocessing for %s", szNiceName);
|
||||
NZBDownloaded(pDownloadQueue, pHistoryInfo->GetNZBInfo());
|
||||
}
|
||||
|
||||
if (bUnparked || bReprocess)
|
||||
{
|
||||
delete pHistoryInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void PrePostProcessor::HistorySetParameter(HistoryInfo* pHistoryInfo, const char* szText)
|
||||
{
|
||||
char szNiceName[1024];
|
||||
pHistoryInfo->GetName(szNiceName, 1024);
|
||||
debug("Setting post-process-parameter '%s' for '%s'", szText, szNiceName);
|
||||
|
||||
if (pHistoryInfo->GetKind() != HistoryInfo::hkNZBInfo)
|
||||
{
|
||||
error("Could not set post-process-parameter for %s: history item has wrong type", szNiceName);
|
||||
return;
|
||||
}
|
||||
|
||||
char* szStr = strdup(szText);
|
||||
|
||||
char* szValue = strchr(szStr, '=');
|
||||
if (szValue)
|
||||
{
|
||||
*szValue = '\0';
|
||||
szValue++;
|
||||
pHistoryInfo->GetNZBInfo()->SetParameter(szStr, szValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not set post-process-parameter for %s: invalid argument: %s", pHistoryInfo->GetNZBInfo()->GetName(), szText);
|
||||
}
|
||||
|
||||
free(szStr);
|
||||
if (bOK)
|
||||
{
|
||||
SaveQueue(pDownloadQueue);
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "Thread.h"
|
||||
#include "Observer.h"
|
||||
#include "DownloadInfo.h"
|
||||
#include "Scanner.h"
|
||||
#include "ParCoordinator.h"
|
||||
|
||||
class PrePostProcessor : public Thread
|
||||
@@ -44,8 +45,7 @@ public:
|
||||
eaPostDelete,
|
||||
eaHistoryDelete,
|
||||
eaHistoryReturn,
|
||||
eaHistoryProcess,
|
||||
eaHistorySetParameter
|
||||
eaHistoryProcess
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -71,16 +71,18 @@ private:
|
||||
PostParCoordinator m_ParCoordinator;
|
||||
QueueCoordinatorObserver m_QueueCoordinatorObserver;
|
||||
bool m_bHasMoreJobs;
|
||||
bool m_bPostScript;
|
||||
bool m_bSchedulerPauseChanged;
|
||||
bool m_bSchedulerPause;
|
||||
bool m_bPostPause;
|
||||
Scanner m_Scanner;
|
||||
const char* m_szPauseReason;
|
||||
|
||||
bool IsNZBFileCompleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo,
|
||||
bool bIgnorePausedPars, bool bAllowOnlyOneDeleted);
|
||||
bool bIgnorePausedPars, bool bCheckPostQueue, bool bAllowOnlyOneDeleted);
|
||||
void CheckPostQueue();
|
||||
void JobCompleted(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo);
|
||||
void StartJob(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo);
|
||||
void StartProcessJob(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo);
|
||||
void SaveQueue(DownloadQueue* pDownloadQueue);
|
||||
void SanitisePostQueue(PostQueue* pPostQueue);
|
||||
void CheckDiskSpace();
|
||||
@@ -93,14 +95,13 @@ private:
|
||||
void NZBDownloaded(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void NZBDeleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void NZBCompleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo, bool bSaveQueue);
|
||||
bool CreatePostJobs(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo, bool bParCheck, bool bUnpackOrScript, bool bAddTop);
|
||||
void DeleteQueuedFile(const char* szQueuedFile);
|
||||
NZBInfo* MergeGroups(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
bool PostQueueMove(IDList* pIDList, EEditAction eAction, int iOffset);
|
||||
bool PostQueueDelete(IDList* pIDList);
|
||||
bool HistoryEdit(IDList* pIDList, EEditAction eAction, int iOffset, const char* szText);
|
||||
void HistoryDelete(DownloadQueue* pDownloadQueue, HistoryList::iterator itHistory, HistoryInfo* pHistoryInfo);
|
||||
void HistoryReturn(DownloadQueue* pDownloadQueue, HistoryList::iterator itHistory, HistoryInfo* pHistoryInfo, bool bReprocess);
|
||||
void HistorySetParameter(HistoryInfo* pHistoryInfo, const char* szText);
|
||||
bool HistoryDelete(IDList* pIDList);
|
||||
bool HistoryReturn(IDList* pIDList, bool bReprocess);
|
||||
void Cleanup();
|
||||
FileInfo* GetQueueGroup(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void CheckHistory();
|
||||
@@ -113,7 +114,8 @@ public:
|
||||
virtual void Stop();
|
||||
void QueueCoordinatorUpdate(Subject* Caller, void* Aspect);
|
||||
bool HasMoreJobs() { return m_bHasMoreJobs; }
|
||||
bool QueueEditList(IDList* pIDList, EEditAction eAction, int iOffset, const char* szText);
|
||||
void ScanNZBDir(bool bSyncMode);
|
||||
bool QueueEditList(IDList* pIDList, EEditAction eAction, int iOffset);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
@@ -117,17 +117,6 @@ void QueueCoordinator::Run()
|
||||
|
||||
m_mutexDownloadQueue.Unlock();
|
||||
|
||||
// compute maximum number of allowed download threads
|
||||
m_iDownloadsLimit = 2; // two extra threads for completing files (when connections are not needed)
|
||||
for (ServerPool::Servers::iterator it = g_pServerPool->GetServers()->begin(); it != g_pServerPool->GetServers()->end(); it++)
|
||||
{
|
||||
NewsServer* pNewsServer = *it;
|
||||
if (pNewsServer->GetLevel() == 0)
|
||||
{
|
||||
m_iDownloadsLimit += pNewsServer->GetMaxConnections();
|
||||
}
|
||||
}
|
||||
|
||||
m_tStartServer = time(NULL);
|
||||
m_tLastCheck = m_tStartServer;
|
||||
bool bWasStandBy = true;
|
||||
@@ -144,27 +133,21 @@ void QueueCoordinator::Run()
|
||||
// start download for next article
|
||||
FileInfo* pFileInfo;
|
||||
ArticleInfo* pArticleInfo;
|
||||
bool bFreeConnection = false;
|
||||
|
||||
|
||||
m_mutexDownloadQueue.Lock();
|
||||
bool bHasMoreArticles = GetNextArticle(pFileInfo, pArticleInfo);
|
||||
bArticeDownloadsRunning = !m_ActiveDownloads.empty();
|
||||
m_bHasMoreJobs = bHasMoreArticles || bArticeDownloadsRunning;
|
||||
if (bHasMoreArticles && !IsStopped() && (int)m_ActiveDownloads.size() < m_iDownloadsLimit)
|
||||
if (bHasMoreArticles && !IsStopped() && Thread::GetThreadCount() < g_pOptions->GetThreadLimit())
|
||||
{
|
||||
StartArticleDownload(pFileInfo, pArticleInfo, pConnection);
|
||||
bArticeDownloadsRunning = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bFreeConnection = true;
|
||||
}
|
||||
m_mutexDownloadQueue.Unlock();
|
||||
|
||||
if (bFreeConnection)
|
||||
{
|
||||
g_pServerPool->FreeConnection(pConnection, false);
|
||||
}
|
||||
m_mutexDownloadQueue.Unlock();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -565,11 +548,7 @@ void QueueCoordinator::StartArticleDownload(FileInfo* pFileInfo, ArticleInfo* pA
|
||||
pArticleDownloader->SetFileInfo(pFileInfo);
|
||||
pArticleDownloader->SetArticleInfo(pArticleInfo);
|
||||
pArticleDownloader->SetConnection(pConnection);
|
||||
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "%s%c%s [%i/%i]", pFileInfo->GetNZBInfo()->GetName(), (int)PATH_SEPARATOR, pFileInfo->GetFilename(), pArticleInfo->GetPartNumber(), pFileInfo->GetArticles()->size());
|
||||
szInfoName[1024-1] = '\0';
|
||||
pArticleDownloader->SetInfoName(szInfoName);
|
||||
BuildArticleFilename(pArticleDownloader, pFileInfo, pArticleInfo);
|
||||
|
||||
pArticleInfo->SetStatus(ArticleInfo::aiRunning);
|
||||
pFileInfo->SetActiveDownloads(pFileInfo->GetActiveDownloads() + 1);
|
||||
@@ -578,6 +557,45 @@ void QueueCoordinator::StartArticleDownload(FileInfo* pFileInfo, ArticleInfo* pA
|
||||
pArticleDownloader->Start();
|
||||
}
|
||||
|
||||
void QueueCoordinator::BuildArticleFilename(ArticleDownloader* pArticleDownloader, FileInfo* pFileInfo, ArticleInfo* pArticleInfo)
|
||||
{
|
||||
char name[1024];
|
||||
|
||||
snprintf(name, 1024, "%s%i.%03i", g_pOptions->GetTempDir(), pFileInfo->GetID(), pArticleInfo->GetPartNumber());
|
||||
name[1024-1] = '\0';
|
||||
pArticleInfo->SetResultFilename(name);
|
||||
|
||||
char tmpname[1024];
|
||||
snprintf(tmpname, 1024, "%s.tmp", name);
|
||||
tmpname[1024-1] = '\0';
|
||||
pArticleDownloader->SetTempFilename(tmpname);
|
||||
|
||||
snprintf(name, 1024, "%s%c%s [%i/%i]", pFileInfo->GetNZBInfo()->GetName(), (int)PATH_SEPARATOR, pFileInfo->GetFilename(), pArticleInfo->GetPartNumber(), pFileInfo->GetArticles()->size());
|
||||
name[1024-1] = '\0';
|
||||
pArticleDownloader->SetInfoName(name);
|
||||
|
||||
if (g_pOptions->GetDirectWrite())
|
||||
{
|
||||
pFileInfo->LockOutputFile();
|
||||
|
||||
if (pFileInfo->GetOutputFilename())
|
||||
{
|
||||
strncpy(name, pFileInfo->GetOutputFilename(), 1024);
|
||||
name[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(name, 1024, "%s%c%i.out.tmp", pFileInfo->GetNZBInfo()->GetDestDir(), (int)PATH_SEPARATOR, pFileInfo->GetID());
|
||||
name[1024-1] = '\0';
|
||||
pFileInfo->SetOutputFilename(name);
|
||||
}
|
||||
|
||||
pFileInfo->UnlockOutputFile();
|
||||
|
||||
pArticleDownloader->SetOutputFilename(name);
|
||||
}
|
||||
}
|
||||
|
||||
DownloadQueue* QueueCoordinator::LockQueue()
|
||||
{
|
||||
m_mutexDownloadQueue.Lock();
|
||||
@@ -644,7 +662,6 @@ void QueueCoordinator::ArticleCompleted(ArticleDownloader* pArticleDownloader)
|
||||
{
|
||||
warn("File \"%s\" seems to be duplicate, cancelling download and deleting file from queue", pFileInfo->GetFilename());
|
||||
fileCompleted = false;
|
||||
pFileInfo->SetAutoDeleted(true);
|
||||
DeleteQueueEntry(pFileInfo);
|
||||
}
|
||||
}
|
||||
@@ -926,7 +943,7 @@ void QueueCoordinator::AdjustStartTime()
|
||||
if (tDiff > 60 || tDiff < 0)
|
||||
{
|
||||
m_tStartServer += tDiff + 1; // "1" because the method is called once per second
|
||||
if (m_tStartDownload != 0 && !m_bStandBy)
|
||||
if (m_tStartDownload != 0)
|
||||
{
|
||||
m_tStartDownload += tDiff + 1;
|
||||
}
|
||||
@@ -1031,76 +1048,3 @@ bool QueueCoordinator::MergeQueueEntries(NZBInfo* pDestNZBInfo, NZBInfo* pSrcNZB
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates new nzb-item out of existing files from other nzb-items.
|
||||
* If any of file-items is being downloaded the command fail.
|
||||
* For each file-item an event "eaFileDeleted" is fired.
|
||||
*
|
||||
* NOTE: DownloadQueue must be locked prior to call of this function
|
||||
*/
|
||||
bool QueueCoordinator::SplitQueueEntries(FileQueue* pFileList, const char* szName, NZBInfo** pNewNZBInfo)
|
||||
{
|
||||
if (pFileList->empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NZBInfo* pSrcNZBInfo = NULL;
|
||||
|
||||
for (FileQueue::iterator it = pFileList->begin(); it != pFileList->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetActiveDownloads() > 0 || pFileInfo->GetCompleted() > 0)
|
||||
{
|
||||
error("Could not split %s. File is already (partially) downloaded", pFileInfo->GetFilename());
|
||||
return false;
|
||||
}
|
||||
if (pFileInfo->GetNZBInfo()->GetPostProcess())
|
||||
{
|
||||
error("Could not split %s. File in post-process-stage", pFileInfo->GetFilename());
|
||||
return false;
|
||||
}
|
||||
if (!pSrcNZBInfo)
|
||||
{
|
||||
pSrcNZBInfo = pFileInfo->GetNZBInfo();
|
||||
}
|
||||
}
|
||||
|
||||
NZBInfo* pNZBInfo = new NZBInfo();
|
||||
pNZBInfo->AddReference();
|
||||
m_DownloadQueue.GetNZBInfoList()->Add(pNZBInfo);
|
||||
|
||||
pNZBInfo->SetFilename(pSrcNZBInfo->GetFilename());
|
||||
pNZBInfo->SetName(szName);
|
||||
pNZBInfo->SetCategory(pSrcNZBInfo->GetCategory());
|
||||
pNZBInfo->BuildDestDirName();
|
||||
pNZBInfo->SetQueuedFilename(pSrcNZBInfo->GetQueuedFilename());
|
||||
|
||||
for (NZBParameterList::iterator it = pSrcNZBInfo->GetParameters()->begin(); it != pSrcNZBInfo->GetParameters()->end(); it++)
|
||||
{
|
||||
NZBParameter* pNZBParameter = *it;
|
||||
pNZBInfo->SetParameter(pNZBParameter->GetName(), pNZBParameter->GetValue());
|
||||
}
|
||||
|
||||
for (FileQueue::iterator it = pFileList->begin(); it != pFileList->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
|
||||
Aspect aspect = { eaFileDeleted, &m_DownloadQueue, pFileInfo->GetNZBInfo(), pFileInfo };
|
||||
Notify(&aspect);
|
||||
|
||||
pFileInfo->SetNZBInfo(pNZBInfo);
|
||||
|
||||
pSrcNZBInfo->SetFileCount(pSrcNZBInfo->GetFileCount() - 1);
|
||||
pSrcNZBInfo->SetSize(pSrcNZBInfo->GetSize() - pFileInfo->GetSize());
|
||||
|
||||
pNZBInfo->SetFileCount(pNZBInfo->GetFileCount() + 1);
|
||||
pNZBInfo->SetSize(pNZBInfo->GetSize() + pFileInfo->GetSize());
|
||||
}
|
||||
|
||||
pNZBInfo->Release();
|
||||
|
||||
*pNewNZBInfo = pNZBInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ private:
|
||||
QueueEditor m_QueueEditor;
|
||||
Mutex m_mutexDownloadQueue;
|
||||
bool m_bHasMoreJobs;
|
||||
int m_iDownloadsLimit;
|
||||
|
||||
// statistics
|
||||
static const int SPEEDMETER_SLOTS = 30;
|
||||
@@ -90,6 +89,7 @@ private:
|
||||
|
||||
bool GetNextArticle(FileInfo* &pFileInfo, ArticleInfo* &pArticleInfo);
|
||||
void StartArticleDownload(FileInfo* pFileInfo, ArticleInfo* pArticleInfo, NNTPConnection* pConnection);
|
||||
void BuildArticleFilename(ArticleDownloader* pArticleDownloader, FileInfo* pFileInfo, ArticleInfo* pArticleInfo);
|
||||
bool IsDupe(FileInfo* pFileInfo);
|
||||
void ArticleCompleted(ArticleDownloader* pArticleDownloader);
|
||||
void DeleteFileInfo(FileInfo* pFileInfo, bool bCompleted);
|
||||
@@ -121,7 +121,6 @@ public:
|
||||
bool SetQueueEntryNZBCategory(NZBInfo* pNZBInfo, const char* szCategory);
|
||||
bool SetQueueEntryNZBName(NZBInfo* pNZBInfo, const char* szName);
|
||||
bool MergeQueueEntries(NZBInfo* pDestNZBInfo, NZBInfo* pSrcNZBInfo);
|
||||
bool SplitQueueEntries(FileQueue* pFileList, const char* szName, NZBInfo** pNewNZBInfo);
|
||||
void DiscardDiskFile(FileInfo* pFileInfo);
|
||||
QueueEditor* GetQueueEditor() { return &m_QueueEditor; }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,8 +33,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
#include <set>
|
||||
#ifndef WIN32
|
||||
@@ -227,11 +227,7 @@ bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList,
|
||||
}
|
||||
else if (eAction == eaGroupMerge)
|
||||
{
|
||||
return MergeGroups(pDownloadQueue, &cItemList);
|
||||
}
|
||||
else if (eAction == eaFileSplit)
|
||||
{
|
||||
return SplitGroup(pDownloadQueue, &cItemList, szText);
|
||||
MergeGroups(pDownloadQueue, &cItemList);
|
||||
}
|
||||
else if (eAction == eaFileReorder)
|
||||
{
|
||||
@@ -294,7 +290,6 @@ bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList,
|
||||
case eaFilePauseExtraPars:
|
||||
case eaGroupMerge:
|
||||
case eaFileReorder:
|
||||
case eaFileSplit:
|
||||
// remove compiler warning "enumeration not handled in switch"
|
||||
break;
|
||||
}
|
||||
@@ -548,8 +543,8 @@ bool QueueEditor::EditGroup(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo,
|
||||
pFileInfo->GetNZBInfo()->SetCleanupDisk(CanCleanupDisk(pDownloadQueue, pFileInfo->GetNZBInfo()));
|
||||
}
|
||||
|
||||
EEditAction GroupToFileMap[] = { (EEditAction)0, eaFileMoveOffset, eaFileMoveTop, eaFileMoveBottom, eaFilePause,
|
||||
eaFileResume, eaFileDelete, eaFilePauseAllPars, eaFilePauseExtraPars, eaFileSetPriority, eaFileReorder, eaFileSplit,
|
||||
EEditAction GroupToFileMap[] = { (EEditAction)0, eaFileMoveOffset, eaFileMoveTop, eaFileMoveBottom,
|
||||
eaFilePause, eaFileResume, eaFileDelete, eaFilePauseAllPars, eaFilePauseExtraPars, eaFileSetPriority, eaFileReorder,
|
||||
eaFileMoveOffset, eaFileMoveTop, eaFileMoveBottom, eaFilePause, eaFileResume, eaFileDelete,
|
||||
eaFilePauseAllPars, eaFilePauseExtraPars, eaFileSetPriority,
|
||||
(EEditAction)0, (EEditAction)0, (EEditAction)0 };
|
||||
@@ -839,15 +834,13 @@ bool QueueEditor::CanCleanupDisk(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInf
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueueEditor::MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList)
|
||||
void QueueEditor::MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList)
|
||||
{
|
||||
if (pItemList->size() == 0)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool bOK = true;
|
||||
|
||||
EditItem* pDestItem = pItemList->front();
|
||||
|
||||
for (ItemList::iterator it = pItemList->begin() + 1; it != pItemList->end(); it++)
|
||||
@@ -856,45 +849,15 @@ bool QueueEditor::MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList
|
||||
if (pItem->m_pFileInfo->GetNZBInfo() != pDestItem->m_pFileInfo->GetNZBInfo())
|
||||
{
|
||||
debug("merge %s to %s", pItem->m_pFileInfo->GetNZBInfo()->GetFilename(), pDestItem->m_pFileInfo->GetNZBInfo()->GetFilename());
|
||||
if (g_pQueueCoordinator->MergeQueueEntries(pDestItem->m_pFileInfo->GetNZBInfo(), pItem->m_pFileInfo->GetNZBInfo()))
|
||||
{
|
||||
bOK = false;
|
||||
}
|
||||
g_pQueueCoordinator->MergeQueueEntries(pDestItem->m_pFileInfo->GetNZBInfo(), pItem->m_pFileInfo->GetNZBInfo());
|
||||
}
|
||||
delete pItem;
|
||||
}
|
||||
|
||||
// align group
|
||||
AlignGroup(pDownloadQueue, pDestItem->m_pFileInfo->GetNZBInfo());
|
||||
|
||||
delete pDestItem;
|
||||
return bOK;
|
||||
}
|
||||
|
||||
bool QueueEditor::SplitGroup(DownloadQueue* pDownloadQueue, ItemList* pItemList, const char* szName)
|
||||
{
|
||||
if (pItemList->size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FileQueue* pFileList = new FileQueue();
|
||||
|
||||
for (ItemList::iterator it = pItemList->begin(); it != pItemList->end(); it++)
|
||||
{
|
||||
EditItem* pItem = *it;
|
||||
pFileList->push_back(pItem->m_pFileInfo);
|
||||
delete pItem;
|
||||
}
|
||||
|
||||
NZBInfo* pNewNZBInfo = NULL;
|
||||
bool bOK = g_pQueueCoordinator->SplitQueueEntries(pFileList, szName, &pNewNZBInfo);
|
||||
if (bOK)
|
||||
{
|
||||
AlignGroup(pDownloadQueue, pNewNZBInfo);
|
||||
}
|
||||
|
||||
delete pFileList;
|
||||
return bOK;
|
||||
}
|
||||
|
||||
void QueueEditor::ReorderFiles(DownloadQueue* pDownloadQueue, ItemList* pItemList)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -45,7 +45,6 @@ public:
|
||||
eaFilePauseExtraPars,
|
||||
eaFileSetPriority,
|
||||
eaFileReorder,
|
||||
eaFileSplit,
|
||||
eaGroupMoveOffset, // move to m_iOffset relative to the current position in queue
|
||||
eaGroupMoveTop,
|
||||
eaGroupMoveBottom,
|
||||
@@ -97,8 +96,7 @@ private:
|
||||
void SetNZBCategory(NZBInfo* pNZBInfo, const char* szCategory);
|
||||
void SetNZBName(NZBInfo* pNZBInfo, const char* szName);
|
||||
bool CanCleanupDisk(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
bool MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList);
|
||||
bool SplitGroup(DownloadQueue* pDownloadQueue, ItemList* pItemList, const char* szName);
|
||||
void MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList);
|
||||
void ReorderFiles(DownloadQueue* pDownloadQueue, ItemList* pItemList);
|
||||
void SetNZBParameter(NZBInfo* pNZBInfo, const char* szParamString);
|
||||
|
||||
|
||||
43
README
43
README
@@ -429,28 +429,40 @@ same computer)
|
||||
Security warning
|
||||
----------------
|
||||
|
||||
NZBGet communicates via unsecured socket connections. This makes it vulnerable.
|
||||
Although server checks the password passed by client, this password is still
|
||||
transmitted in unsecured way. For this reason it is highly recommended
|
||||
to configure your Firewall to not expose the port used by NZBGet to WAN.
|
||||
NZBGet client communicates with NZBGet server via unsecured socket connections.
|
||||
This makes it vulnerable. Although server checks the password passed by client,
|
||||
this password is still transmitted in unsecured way. For this reason it is
|
||||
highly recommended to configure your firewall to not expose the port used by
|
||||
NZBGet (option <ControlPort>) to WAN.
|
||||
|
||||
If you need to control server from WAN it is better to connect to server's
|
||||
terminal via SSH (POSIX) or remote desktop (Windows) and then run
|
||||
nzbget-client-commands in this terminal.
|
||||
If you need to control server from WAN it is better to use web-interface via HTTPS
|
||||
or (if you prefer remote commands) connect to server's terminal via SSH (POSIX)
|
||||
or remote desktop (Windows) and then run nzbget-client-commands in this terminal.
|
||||
|
||||
Post processing scripts
|
||||
-----------------------
|
||||
|
||||
After the download of nzb-file is completed nzbget can call post-processing
|
||||
scripts, defined in configuration file.
|
||||
script, defined in configuration file. See example configuration file for
|
||||
the description of parameters passed to the script (option "PostProcess").
|
||||
|
||||
Example post-processing scripts are provided in directory "ppscripts".
|
||||
An example script for unraring of downloaded files is provided in file
|
||||
"nzbget-postprocess.sh" installed into "<prefix>/bin". The script requires
|
||||
configuration file "nzbget-postprocess.conf". If you have installed the
|
||||
program with "make install" this file is copied to "<prefix>/etc",
|
||||
where the post-processing script finds it automatically. If you install
|
||||
the program manually from a binary archive you have to copy the file
|
||||
from "<prefix>/share/nzbget" to the directory where you have put the
|
||||
nzbget configuration file ("nzbget.conf").
|
||||
|
||||
To use the scripts copy them into your local directory and set options
|
||||
<ScriptDir>, <DefScript> and <ScriptOrder>.
|
||||
Set the option "PostProcess" in "nzbget.conf" to point to the post-
|
||||
processing script.
|
||||
|
||||
For information on writing your own post-processing scripts please
|
||||
visit NZBGet web site.
|
||||
Additional usage instructions are included in "nzbget-postprocess.sh",
|
||||
please open the file in a text editor to read them.
|
||||
|
||||
NOTE: The post-processing script "nzbget-postprocess.sh" is for
|
||||
POSIX systems and will not work on Windows.
|
||||
|
||||
Web-interface
|
||||
-------------
|
||||
@@ -512,8 +524,11 @@ Binary distribution for Windows contains code from the following libraries:
|
||||
- libpar2 (http://parchive.sourceforge.net)
|
||||
- libsigc++ (http://libsigc.sourceforge.net)
|
||||
- GnuTLS (http://www.gnu.org/software/gnutls)
|
||||
- zlib (http://www.zlib.net)
|
||||
- regex (http://gnuwin32.sourceforge.net/packages/regex.htm)
|
||||
|
||||
libpar2 is distributed under GPL; libsigc++ and GnuTLS - under LGPL.
|
||||
libpar2 is distributed under GPL; libsigc++, GnuTLS and regex - under LGPL;
|
||||
zlib - under zlib license.
|
||||
|
||||
=====================================
|
||||
10. Contact
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
@@ -126,10 +126,6 @@ void RemoteClient::InitMessageBase(SNZBRequestBase* pMessageBase, int iRequest,
|
||||
pMessageBase->m_iSignature = htonl(NZBMESSAGE_SIGNATURE);
|
||||
pMessageBase->m_iType = htonl(iRequest);
|
||||
pMessageBase->m_iStructSize = htonl(iSize);
|
||||
|
||||
strncpy(pMessageBase->m_szUsername, g_pOptions->GetControlUsername(), NZBREQUESTPASSWORDSIZE - 1);
|
||||
pMessageBase->m_szUsername[NZBREQUESTPASSWORDSIZE - 1] = '\0';
|
||||
|
||||
strncpy(pMessageBase->m_szPassword, g_pOptions->GetControlPassword(), NZBREQUESTPASSWORDSIZE - 1);
|
||||
pMessageBase->m_szPassword[NZBREQUESTPASSWORDSIZE - 1] = '\0';
|
||||
}
|
||||
@@ -188,7 +184,7 @@ bool RemoteClient::RequestServerDownload(const char* szFilename, const char* szC
|
||||
DownloadRequest.m_bAddFirst = htonl(bAddFirst);
|
||||
DownloadRequest.m_bAddPaused = htonl(bAddPaused);
|
||||
DownloadRequest.m_iPriority = htonl(iPriority);
|
||||
DownloadRequest.m_iTrailingDataLength = htonl(iLength - 1);
|
||||
DownloadRequest.m_iTrailingDataLength = htonl(iLength);
|
||||
|
||||
strncpy(DownloadRequest.m_szFilename, szFilename, NZBREQUESTFILENAMESIZE - 1);
|
||||
DownloadRequest.m_szFilename[NZBREQUESTFILENAMESIZE-1] = '\0';
|
||||
@@ -1039,13 +1035,13 @@ bool RemoteClient::RequestPostQueue()
|
||||
}
|
||||
|
||||
const char* szPostStageName[] = { "", ", Loading Pars", ", Verifying source files", ", Repairing", ", Verifying repaired files", ", Unpacking", ", Executing postprocess-script", "" };
|
||||
char* szInfoName = pBufPtr + sizeof(SNZBPostQueueResponseEntry) + ntohl(pPostQueueAnswer->m_iNZBFilenameLen);
|
||||
char* szInfoName = pBufPtr + sizeof(SNZBPostQueueResponseEntry) + ntohl(pPostQueueAnswer->m_iNZBFilenameLen) + ntohl(pPostQueueAnswer->m_iParFilename);
|
||||
|
||||
printf("[%i] %s%s%s\n", ntohl(pPostQueueAnswer->m_iID), szInfoName, szPostStageName[ntohl(pPostQueueAnswer->m_iStage)], szCompleted);
|
||||
|
||||
pBufPtr += sizeof(SNZBPostQueueResponseEntry) + ntohl(pPostQueueAnswer->m_iNZBFilenameLen) +
|
||||
ntohl(pPostQueueAnswer->m_iInfoNameLen) + ntohl(pPostQueueAnswer->m_iDestDirLen) +
|
||||
ntohl(pPostQueueAnswer->m_iProgressLabelLen);
|
||||
ntohl(pPostQueueAnswer->m_iParFilename) + ntohl(pPostQueueAnswer->m_iInfoNameLen) +
|
||||
ntohl(pPostQueueAnswer->m_iDestDirLen) + ntohl(pPostQueueAnswer->m_iProgressLabelLen);
|
||||
}
|
||||
|
||||
free(pBuf);
|
||||
@@ -1164,7 +1160,7 @@ bool RemoteClient::RequestHistory()
|
||||
char szSize[20];
|
||||
Util::FormatFileSize(szSize, sizeof(szSize), lSize);
|
||||
|
||||
const char* szParStatusText[] = { "", "", ", Par failed", ", Par successful", ", Repair possible", ", Repair needed" };
|
||||
const char* szParStatusText[] = { "", ", Par failed", ", Par possible", ", Par successful" };
|
||||
const char* szScriptStatusText[] = { "", ", Script status unknown", ", Script failed", ", Script successful" };
|
||||
|
||||
printf("[%i] %s (%i files, %s%s%s)\n", ntohl(pListAnswer->m_iID), szNicename,
|
||||
|
||||
@@ -104,7 +104,7 @@ void RemoteServer::Run()
|
||||
m_bTLS);
|
||||
m_pConnection->SetTimeout(g_pOptions->GetConnectionTimeout());
|
||||
m_pConnection->SetSuppressErrors(false);
|
||||
bBind = m_pConnection->Bind();
|
||||
bBind = m_pConnection->Bind() == 0;
|
||||
}
|
||||
|
||||
// Accept connections and store the new Connection
|
||||
|
||||
208
Scanner.cpp
208
Scanner.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,13 +33,14 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Scanner.h"
|
||||
@@ -66,41 +67,6 @@ Scanner::FileData::~FileData()
|
||||
free(m_szFilename);
|
||||
}
|
||||
|
||||
|
||||
Scanner::QueueData::QueueData(const char* szFilename, const char* szNZBName, const char* szCategory, int iPriority,
|
||||
NZBParameterList* pParameters, bool bAddTop, bool bAddPaused)
|
||||
{
|
||||
m_szFilename = strdup(szFilename);
|
||||
m_szNZBName = strdup(szNZBName);
|
||||
m_szCategory = strdup(szCategory ? szCategory : "");
|
||||
m_iPriority = iPriority;
|
||||
m_bAddTop = bAddTop;
|
||||
m_bAddPaused = bAddPaused;
|
||||
|
||||
if (pParameters)
|
||||
{
|
||||
for (NZBParameterList::iterator it = pParameters->begin(); it != pParameters->end(); it++)
|
||||
{
|
||||
NZBParameter* pNZBParameter = *it;
|
||||
m_Parameters.SetParameter(pNZBParameter->GetName(), pNZBParameter->GetValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Scanner::QueueData::~QueueData()
|
||||
{
|
||||
free(m_szFilename);
|
||||
free(m_szNZBName);
|
||||
free(m_szCategory);
|
||||
|
||||
for (NZBParameterList::iterator it = m_Parameters.begin(); it != m_Parameters.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_Parameters.clear();
|
||||
}
|
||||
|
||||
|
||||
Scanner::Scanner()
|
||||
{
|
||||
debug("Creating Scanner");
|
||||
@@ -109,6 +75,7 @@ Scanner::Scanner()
|
||||
m_bScanning = false;
|
||||
m_iNZBDirInterval = g_pOptions->GetNzbDirInterval() * 1000;
|
||||
m_iPass = 0;
|
||||
m_iStepMSec = 0;
|
||||
|
||||
const char* szNZBScript = g_pOptions->GetNZBProcess();
|
||||
m_bNZBScript = szNZBScript && strlen(szNZBScript) > 0;
|
||||
@@ -123,26 +90,13 @@ Scanner::~Scanner()
|
||||
delete *it;
|
||||
}
|
||||
m_FileList.clear();
|
||||
|
||||
ClearQueueList();
|
||||
}
|
||||
|
||||
void Scanner::ClearQueueList()
|
||||
{
|
||||
for (QueueList::iterator it = m_QueueList.begin(); it != m_QueueList.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_QueueList.clear();
|
||||
}
|
||||
|
||||
void Scanner::Check()
|
||||
{
|
||||
m_mutexScan.Lock();
|
||||
|
||||
if (m_bRequestedNZBDirScan ||
|
||||
if (g_pOptions->GetNzbDir() && (m_bRequestedNZBDirScan ||
|
||||
(!g_pOptions->GetPauseScan() && g_pOptions->GetNzbDirInterval() > 0 &&
|
||||
m_iNZBDirInterval >= g_pOptions->GetNzbDirInterval() * 1000))
|
||||
m_iNZBDirInterval >= g_pOptions->GetNzbDirInterval() * 1000)))
|
||||
{
|
||||
// check nzbdir every g_pOptions->GetNzbDirInterval() seconds or if requested
|
||||
bool bCheckStat = !m_bRequestedNZBDirScan;
|
||||
@@ -151,7 +105,7 @@ void Scanner::Check()
|
||||
CheckIncomingNZBs(g_pOptions->GetNzbDir(), "", bCheckStat);
|
||||
if (!bCheckStat && m_bNZBScript)
|
||||
{
|
||||
// if immediate scan requested, we need second scan to process files extracted by NzbProcess-script
|
||||
// if immediate scan requesten, we need second scan to process files extracted by NzbProcess-script
|
||||
CheckIncomingNZBs(g_pOptions->GetNzbDir(), "", bCheckStat);
|
||||
}
|
||||
m_bScanning = false;
|
||||
@@ -162,7 +116,7 @@ void Scanner::Check()
|
||||
// - one additional scan is neccessary to check sizes of detected files;
|
||||
// - another scan is required to check files which were extracted by NzbProcess-script;
|
||||
// - third scan is needed to check sizes of extracted files.
|
||||
if (g_pOptions->GetNzbDirInterval() > 0 && g_pOptions->GetNzbDirFileAge() < g_pOptions->GetNzbDirInterval())
|
||||
if (g_pOptions->GetNzbDirFileAge() < g_pOptions->GetNzbDirInterval())
|
||||
{
|
||||
int iMaxPass = m_bNZBScript ? 3 : 1;
|
||||
if (m_iPass < iMaxPass)
|
||||
@@ -179,10 +133,7 @@ void Scanner::Check()
|
||||
|
||||
DropOldFiles();
|
||||
}
|
||||
m_iNZBDirInterval += 200;
|
||||
|
||||
ClearQueueList();
|
||||
m_mutexScan.Unlock();
|
||||
m_iNZBDirInterval += m_iStepMSec;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,34 +278,16 @@ void Scanner::ProcessIncomingFile(const char* szDirectory, const char* szBaseFil
|
||||
return;
|
||||
}
|
||||
|
||||
char* szNZBName = strdup("");
|
||||
char* szNZBCategory = strdup(szCategory);
|
||||
NZBParameterList* pParameters = new NZBParameterList();
|
||||
NZBParameterList* pParameterList = new NZBParameterList;
|
||||
int iPriority = 0;
|
||||
bool bAddTop = false;
|
||||
bool bAddPaused = false;
|
||||
|
||||
for (QueueList::iterator it = m_QueueList.begin(); it != m_QueueList.end(); it++)
|
||||
{
|
||||
QueueData* pQueueData = *it;
|
||||
if (Util::SameFilename(pQueueData->GetFilename(), szFullFilename))
|
||||
{
|
||||
free(szNZBName);
|
||||
szNZBName = strdup(pQueueData->GetNZBName());
|
||||
free(szNZBCategory);
|
||||
szNZBCategory = strdup(pQueueData->GetCategory());
|
||||
iPriority = pQueueData->GetPriority();
|
||||
bAddTop = pQueueData->GetAddTop();
|
||||
bAddPaused = pQueueData->GetAddPaused();
|
||||
}
|
||||
}
|
||||
|
||||
bool bExists = true;
|
||||
|
||||
if (m_bNZBScript && strcasecmp(szExtension, ".nzb_processed"))
|
||||
{
|
||||
NZBScriptController::ExecuteScript(g_pOptions->GetNZBProcess(), szFullFilename, szDirectory,
|
||||
&szNZBName, &szNZBCategory, &iPriority, pParameters, &bAddTop, &bAddPaused);
|
||||
&szNZBCategory, &iPriority, pParameterList);
|
||||
bExists = Util::FileExists(szFullFilename);
|
||||
if (bExists && strcasecmp(szExtension, ".nzb"))
|
||||
{
|
||||
@@ -362,8 +295,7 @@ void Scanner::ProcessIncomingFile(const char* szDirectory, const char* szBaseFil
|
||||
bool bRenameOK = Util::RenameBak(szFullFilename, "processed", false, bakname2, 1024);
|
||||
if (!bRenameOK)
|
||||
{
|
||||
char szSysErrStr[256];
|
||||
error("Could not rename file %s to %s: %s", szFullFilename, bakname2, Util::GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
error("Could not rename file %s to %s! Errcode: %i", szFullFilename, bakname2, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,38 +306,35 @@ void Scanner::ProcessIncomingFile(const char* szDirectory, const char* szBaseFil
|
||||
bool bRenameOK = Util::RenameBak(szFullFilename, "nzb", true, szRenamedName, 1024);
|
||||
if (bRenameOK)
|
||||
{
|
||||
AddFileToQueue(szRenamedName, szNZBName, szNZBCategory, iPriority, pParameters, bAddTop, bAddPaused);
|
||||
AddFileToQueue(szRenamedName, szNZBCategory, iPriority, pParameterList);
|
||||
}
|
||||
else
|
||||
{
|
||||
char szSysErrStr[256];
|
||||
error("Could not rename file %s to %s: %s", szFullFilename, szRenamedName, Util::GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
error("Could not rename file %s to %s! Errcode: %i", szFullFilename, szRenamedName, errno);
|
||||
}
|
||||
}
|
||||
else if (bExists && !strcasecmp(szExtension, ".nzb"))
|
||||
{
|
||||
AddFileToQueue(szFullFilename, szNZBName, szNZBCategory, iPriority, pParameters, bAddTop, bAddPaused);
|
||||
AddFileToQueue(szFullFilename, szNZBCategory, iPriority, pParameterList);
|
||||
}
|
||||
|
||||
for (NZBParameterList::iterator it = pParameters->begin(); it != pParameters->end(); it++)
|
||||
for (NZBParameterList::iterator it = pParameterList->begin(); it != pParameterList->end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
pParameters->clear();
|
||||
delete pParameters;
|
||||
pParameterList->clear();
|
||||
delete pParameterList;
|
||||
|
||||
free(szNZBName);
|
||||
free(szNZBCategory);
|
||||
}
|
||||
|
||||
void Scanner::AddFileToQueue(const char* szFilename, const char* szNZBName, const char* szCategory, int iPriority,
|
||||
NZBParameterList* pParameters, bool bAddTop, bool bAddPaused)
|
||||
void Scanner::AddFileToQueue(const char* szFilename, const char* szCategory, int iPriority, NZBParameterList* pParameterList)
|
||||
{
|
||||
const char* szBasename = Util::BaseFileName(szFilename);
|
||||
|
||||
info("Collection %s found", szBasename);
|
||||
|
||||
NZBFile* pNZBFile = NZBFile::Create(szFilename, szCategory);
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromFile(szFilename, szCategory);
|
||||
if (!pNZBFile)
|
||||
{
|
||||
error("Could not add collection %s to queue", szBasename);
|
||||
@@ -415,22 +344,14 @@ void Scanner::AddFileToQueue(const char* szFilename, const char* szNZBName, cons
|
||||
bool bRenameOK = Util::RenameBak(szFilename, pNZBFile ? "queued" : "error", false, bakname2, 1024);
|
||||
if (!bRenameOK)
|
||||
{
|
||||
char szSysErrStr[256];
|
||||
error("Could not rename file %s to %s: %s", szFilename, bakname2, Util::GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
error("Could not rename file %s to %s! Errcode: %i", szFilename, bakname2, errno);
|
||||
}
|
||||
|
||||
if (pNZBFile && bRenameOK)
|
||||
{
|
||||
pNZBFile->GetNZBInfo()->SetQueuedFilename(bakname2);
|
||||
|
||||
if (szNZBName && strlen(szNZBName) > 0)
|
||||
{
|
||||
pNZBFile->GetNZBInfo()->SetName(NULL);
|
||||
pNZBFile->GetNZBInfo()->SetFilename(szNZBName);
|
||||
pNZBFile->GetNZBInfo()->BuildDestDirName();
|
||||
}
|
||||
|
||||
for (NZBParameterList::iterator it = pParameters->begin(); it != pParameters->end(); it++)
|
||||
for (NZBParameterList::iterator it = pParameterList->begin(); it != pParameterList->end(); it++)
|
||||
{
|
||||
NZBParameter* pParameter = *it;
|
||||
pNZBFile->GetNZBInfo()->SetParameter(pParameter->GetName(), pParameter->GetValue());
|
||||
@@ -440,10 +361,9 @@ void Scanner::AddFileToQueue(const char* szFilename, const char* szNZBName, cons
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
pFileInfo->SetPriority(iPriority);
|
||||
pFileInfo->SetPaused(bAddPaused);
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, bAddTop);
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, false);
|
||||
info("Collection %s added to queue", szBasename);
|
||||
}
|
||||
|
||||
@@ -455,91 +375,13 @@ void Scanner::AddFileToQueue(const char* szFilename, const char* szNZBName, cons
|
||||
|
||||
void Scanner::ScanNZBDir(bool bSyncMode)
|
||||
{
|
||||
m_mutexScan.Lock();
|
||||
// ideally we should use mutex to access "m_bRequestedNZBDirScan",
|
||||
// but it's not critical here.
|
||||
m_bScanning = true;
|
||||
m_bRequestedNZBDirScan = true;
|
||||
m_mutexScan.Unlock();
|
||||
|
||||
while (bSyncMode && (m_bScanning || m_bRequestedNZBDirScan))
|
||||
{
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
bool Scanner::AddExternalFile(const char* szNZBName, const char* szCategory, int iPriority,
|
||||
NZBParameterList* pParameters, bool bAddTop, bool bAddPaused,
|
||||
const char* szFileName, const char* szBuffer, int iBufSize, bool bSyncMode)
|
||||
{
|
||||
char szTempFileName[1024];
|
||||
|
||||
if (szFileName)
|
||||
{
|
||||
strncpy(szTempFileName, szFileName, 1024);
|
||||
szTempFileName[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
int iNum = 1;
|
||||
while (iNum == 1 || Util::FileExists(szTempFileName))
|
||||
{
|
||||
snprintf(szTempFileName, 1024, "%snzb-%i.tmp", g_pOptions->GetTempDir(), iNum);
|
||||
szTempFileName[1024-1] = '\0';
|
||||
iNum++;
|
||||
}
|
||||
|
||||
if (!Util::SaveBufferIntoFile(szTempFileName, szBuffer, iBufSize))
|
||||
{
|
||||
error("Could not create file %s", szTempFileName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// move file into NzbDir, make sure the file name is unique
|
||||
char szValidNZBName[1024];
|
||||
strncpy(szValidNZBName, Util::BaseFileName(szNZBName), 1024);
|
||||
szValidNZBName[1024-1] = '\0';
|
||||
Util::MakeValidFilename(szValidNZBName, '_', false);
|
||||
|
||||
char szScanFileName[1024];
|
||||
snprintf(szScanFileName, 1024, "%s%s", g_pOptions->GetNzbDir(), szValidNZBName);
|
||||
|
||||
char *szExt = strrchr(szValidNZBName, '.');
|
||||
if (szExt)
|
||||
{
|
||||
*szExt = '\0';
|
||||
szExt++;
|
||||
}
|
||||
|
||||
int iNum = 2;
|
||||
while (Util::FileExists(szScanFileName))
|
||||
{
|
||||
if (szExt)
|
||||
{
|
||||
snprintf(szScanFileName, 1024, "%s%s_%i.%s", g_pOptions->GetNzbDir(), szValidNZBName, iNum, szExt);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szScanFileName, 1024, "%s%s_%i", g_pOptions->GetNzbDir(), szValidNZBName, iNum);
|
||||
}
|
||||
szScanFileName[1024-1] = '\0';
|
||||
iNum++;
|
||||
}
|
||||
|
||||
if (!Util::MoveFile(szTempFileName, szScanFileName))
|
||||
{
|
||||
char szSysErrStr[256];
|
||||
error("Could not move file %s to %s: %s", szTempFileName, szScanFileName, Util::GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
remove(szTempFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
QueueData* pQueueData = new QueueData(szScanFileName, szNZBName, szCategory, iPriority, pParameters, bAddTop, bAddPaused);
|
||||
|
||||
m_mutexScan.Lock();
|
||||
m_QueueList.push_back(pQueueData);
|
||||
m_mutexScan.Unlock();
|
||||
|
||||
ScanNZBDir(bSyncMode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
40
Scanner.h
40
Scanner.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2011 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <deque>
|
||||
#include <time.h>
|
||||
#include "DownloadInfo.h"
|
||||
#include "Thread.h"
|
||||
|
||||
class Scanner
|
||||
{
|
||||
@@ -53,57 +52,26 @@ private:
|
||||
|
||||
typedef std::deque<FileData*> FileList;
|
||||
|
||||
class QueueData
|
||||
{
|
||||
private:
|
||||
char* m_szFilename;
|
||||
char* m_szNZBName;
|
||||
char* m_szCategory;
|
||||
int m_iPriority;
|
||||
NZBParameterList m_Parameters;
|
||||
bool m_bAddTop;
|
||||
bool m_bAddPaused;
|
||||
|
||||
public:
|
||||
QueueData(const char* szFilename, const char* szNZBName, const char* szCategory, int iPriority,
|
||||
NZBParameterList* pParameters, bool bAddTop, bool bAddPaused);
|
||||
~QueueData();
|
||||
const char* GetFilename() { return m_szFilename; }
|
||||
const char* GetNZBName() { return m_szNZBName; }
|
||||
const char* GetCategory() { return m_szCategory; }
|
||||
int GetPriority() { return m_iPriority; }
|
||||
NZBParameterList* GetParameters() { return &m_Parameters; }
|
||||
bool GetAddTop() { return m_bAddTop; }
|
||||
bool GetAddPaused() { return m_bAddPaused; }
|
||||
};
|
||||
|
||||
typedef std::deque<QueueData*> QueueList;
|
||||
|
||||
bool m_bRequestedNZBDirScan;
|
||||
int m_iNZBDirInterval;
|
||||
bool m_bNZBScript;
|
||||
int m_iPass;
|
||||
int m_iStepMSec;
|
||||
FileList m_FileList;
|
||||
QueueList m_QueueList;
|
||||
bool m_bScanning;
|
||||
Mutex m_mutexScan;
|
||||
|
||||
void CheckIncomingNZBs(const char* szDirectory, const char* szCategory, bool bCheckStat);
|
||||
void AddFileToQueue(const char* szFilename, const char* szNZBName, const char* szCategory, int iPriority,
|
||||
NZBParameterList* pParameters, bool bAddTop, bool bAddPaused);
|
||||
void AddFileToQueue(const char* szFilename, const char* szCategory, int iPriority, NZBParameterList* pParameterList);
|
||||
void ProcessIncomingFile(const char* szDirectory, const char* szBaseFilename, const char* szFullFilename, const char* szCategory);
|
||||
bool CanProcessFile(const char* szFullFilename, bool bCheckStat);
|
||||
void DropOldFiles();
|
||||
void ClearQueueList();
|
||||
|
||||
public:
|
||||
Scanner();
|
||||
~Scanner();
|
||||
void SetStepInterval(int iStepMSec) { m_iStepMSec = iStepMSec; }
|
||||
void ScanNZBDir(bool bSyncMode);
|
||||
void Check();
|
||||
bool AddExternalFile(const char* szNZBName, const char* szCategory, int iPriority,
|
||||
NZBParameterList* pParameters, bool bAddPaused, bool bAddTop,
|
||||
const char* szFileName, const char* szBuffer, int iBufSize, bool bSyncMode);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2008-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2008-2009 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Scheduler.h"
|
||||
|
||||
@@ -57,7 +57,8 @@ extern Options* g_pOptions;
|
||||
extern char* (*g_szEnvironmentVariables)[];
|
||||
extern DownloadQueueHolder* g_pDownloadQueueHolder;
|
||||
|
||||
static const int POSTPROCESS_PARCHECK = 92;
|
||||
static const int POSTPROCESS_PARCHECK_CURRENT = 91;
|
||||
static const int POSTPROCESS_PARCHECK_ALL = 92;
|
||||
static const int POSTPROCESS_SUCCESS = 93;
|
||||
static const int POSTPROCESS_ERROR = 94;
|
||||
static const int POSTPROCESS_NONE = 95;
|
||||
@@ -113,11 +114,6 @@ EnvironmentStrings::EnvironmentStrings()
|
||||
}
|
||||
|
||||
EnvironmentStrings::~EnvironmentStrings()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void EnvironmentStrings::Clear()
|
||||
{
|
||||
for (Strings::iterator it = m_strings.begin(); it != m_strings.end(); it++)
|
||||
{
|
||||
@@ -197,7 +193,7 @@ ScriptController::ScriptController()
|
||||
m_szArgs = NULL;
|
||||
m_bFreeArgs = false;
|
||||
m_szInfoName = NULL;
|
||||
m_szLogPrefix = NULL;
|
||||
m_szDefaultKindPrefix = NULL;
|
||||
m_bTerminated = false;
|
||||
m_environmentStrings.InitFromCurrentProcess();
|
||||
}
|
||||
@@ -214,12 +210,6 @@ ScriptController::~ScriptController()
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptController::ResetEnv()
|
||||
{
|
||||
m_environmentStrings.Clear();
|
||||
m_environmentStrings.InitFromCurrentProcess();
|
||||
}
|
||||
|
||||
void ScriptController::SetEnvVar(const char* szName, const char* szValue)
|
||||
{
|
||||
int iLen = strlen(szName) + strlen(szValue) + 2;
|
||||
@@ -228,139 +218,64 @@ void ScriptController::SetEnvVar(const char* szName, const char* szValue)
|
||||
m_environmentStrings.Append(szVar);
|
||||
}
|
||||
|
||||
/**
|
||||
* If szStripPrefix is not NULL, only options, whose names start with the prefix
|
||||
* are processed. The prefix is then stripped from the names.
|
||||
* If szStripPrefix is NULL, all options are processed; without stripping.
|
||||
*/
|
||||
void ScriptController::PrepareEnvOptions(const char* szStripPrefix)
|
||||
void ScriptController::PrepareEnvOptions()
|
||||
{
|
||||
int iPrefixLen = szStripPrefix ? strlen(szStripPrefix) : 0;
|
||||
|
||||
Options::OptEntries* pOptEntries = g_pOptions->LockOptEntries();
|
||||
|
||||
for (Options::OptEntries::iterator it = pOptEntries->begin(); it != pOptEntries->end(); it++)
|
||||
{
|
||||
Options::OptEntry* pOptEntry = *it;
|
||||
|
||||
if (szStripPrefix && !strncmp(pOptEntry->GetName(), szStripPrefix, iPrefixLen) && (int)strlen(pOptEntry->GetName()) > iPrefixLen)
|
||||
char szVarname[1024];
|
||||
snprintf(szVarname, sizeof(szVarname), "NZBOP_%s", pOptEntry->GetName());
|
||||
|
||||
// convert to upper case; replace "." with "_".
|
||||
for (char* szPtr = szVarname; *szPtr; szPtr++)
|
||||
{
|
||||
SetEnvVarSpecial("NZBPO", pOptEntry->GetName() + iPrefixLen, pOptEntry->GetValue());
|
||||
}
|
||||
else if (!szStripPrefix)
|
||||
{
|
||||
SetEnvVarSpecial("NZBOP", pOptEntry->GetName(), pOptEntry->GetValue());
|
||||
if (*szPtr == '.') *szPtr = '_';
|
||||
*szPtr = toupper(*szPtr);
|
||||
}
|
||||
|
||||
szVarname[1024-1] = '\0';
|
||||
SetEnvVar(szVarname, pOptEntry->GetValue());
|
||||
}
|
||||
|
||||
g_pOptions->UnlockOptEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ScriptController::PrepareEnvParameters(NZBInfo* pNZBInfo, const char* szStripPrefix)
|
||||
void ScriptController::PrepareEnvParameters(NZBInfo* pNZBInfo)
|
||||
{
|
||||
int iPrefixLen = szStripPrefix ? strlen(szStripPrefix) : 0;
|
||||
|
||||
for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++)
|
||||
{
|
||||
NZBParameter* pParameter = *it;
|
||||
|
||||
if (szStripPrefix && !strncmp(pParameter->GetName(), szStripPrefix, iPrefixLen) && (int)strlen(pParameter->GetName()) > iPrefixLen)
|
||||
{
|
||||
SetEnvVarSpecial("NZBPR", pParameter->GetName() + iPrefixLen, pParameter->GetValue());
|
||||
}
|
||||
else if (!szStripPrefix)
|
||||
{
|
||||
SetEnvVarSpecial("NZBPR", pParameter->GetName(), pParameter->GetValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
char szVarname[1024];
|
||||
snprintf(szVarname, sizeof(szVarname), "NZBPR_%s", pParameter->GetName());
|
||||
szVarname[1024-1] = '\0';
|
||||
|
||||
void ScriptController::SetEnvVarSpecial(const char* szPrefix, const char* szName, const char* szValue)
|
||||
{
|
||||
char szVarname[1024];
|
||||
snprintf(szVarname, sizeof(szVarname), "%s_%s", szPrefix, szName);
|
||||
szVarname[1024-1] = '\0';
|
||||
|
||||
// Original name
|
||||
SetEnvVar(szVarname, szValue);
|
||||
|
||||
char szNormVarname[1024];
|
||||
strncpy(szNormVarname, szVarname, sizeof(szVarname));
|
||||
szNormVarname[1024-1] = '\0';
|
||||
|
||||
// Replace special characters with "_" and convert to upper case
|
||||
for (char* szPtr = szNormVarname; *szPtr; szPtr++)
|
||||
{
|
||||
if (strchr(".:*!\"$%&/()=`+~#'{}[]@- ", *szPtr)) *szPtr = '_';
|
||||
*szPtr = toupper(*szPtr);
|
||||
}
|
||||
|
||||
// Another env var with normalized name (replaced special chars and converted to upper case)
|
||||
if (strcmp(szVarname, szNormVarname))
|
||||
{
|
||||
SetEnvVar(szNormVarname, szValue);
|
||||
}
|
||||
}
|
||||
// Original name
|
||||
SetEnvVar(szVarname, pParameter->GetValue());
|
||||
|
||||
void ScriptController::PrepareArgs()
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (!m_szArgs)
|
||||
{
|
||||
// Special support for script languages:
|
||||
// automatically find the app registered for this extension and run it
|
||||
const char* szExtension = strrchr(GetScript(), '.');
|
||||
if (szExtension && strcasecmp(szExtension, ".exe") && strcasecmp(szExtension, ".bat") && strcasecmp(szExtension, ".cmd"))
|
||||
char szNormVarname[1024];
|
||||
strncpy(szNormVarname, szVarname, sizeof(szVarname));
|
||||
szNormVarname[1024-1] = '\0';
|
||||
|
||||
// replace ".*:" with "_".
|
||||
for (char* szPtr = szNormVarname; *szPtr; szPtr++)
|
||||
{
|
||||
debug("Looking for associated program for %s", szExtension);
|
||||
char szCommand[512];
|
||||
int iBufLen = 512-1;
|
||||
if (Util::RegReadStr(HKEY_CLASSES_ROOT, szExtension, NULL, szCommand, &iBufLen))
|
||||
{
|
||||
szCommand[iBufLen] = '\0';
|
||||
debug("Extension: %s", szCommand);
|
||||
|
||||
char szRegPath[512];
|
||||
snprintf(szRegPath, 512, "%s\\shell\\open\\command", szCommand);
|
||||
szRegPath[512-1] = '\0';
|
||||
|
||||
iBufLen = 512-1;
|
||||
if (Util::RegReadStr(HKEY_CLASSES_ROOT, szRegPath, NULL, szCommand, &iBufLen))
|
||||
{
|
||||
szCommand[iBufLen] = '\0';
|
||||
debug("Command: %s", szCommand);
|
||||
|
||||
DWORD_PTR pArgs[] = { (DWORD_PTR)GetScript(), (DWORD_PTR)0 };
|
||||
if (FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, szCommand, 0, 0,
|
||||
m_szCmdLine, sizeof(m_szCmdLine), (va_list*)pArgs))
|
||||
{
|
||||
debug("CmdLine: %s", m_szCmdLine);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
warn("Could not found associated program for %s. Trying to execute %s directly", szExtension, Util::BaseFileName(GetScript()));
|
||||
if (*szPtr == '.' || *szPtr == ':' || *szPtr == '*') *szPtr = '_';
|
||||
*szPtr = toupper(*szPtr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_szArgs)
|
||||
{
|
||||
m_szStdArgs[0] = GetScript();
|
||||
m_szStdArgs[1] = NULL;
|
||||
SetArgs(m_szStdArgs, false);
|
||||
// Another env var with normalized name (replaced special chars and converted to upper case)
|
||||
if (strcmp(szVarname, szNormVarname))
|
||||
{
|
||||
SetEnvVar(szNormVarname, pParameter->GetValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ScriptController::Execute()
|
||||
{
|
||||
PrepareEnvOptions(NULL);
|
||||
PrepareArgs();
|
||||
PrepareEnvOptions();
|
||||
|
||||
int iExitCode = 0;
|
||||
int pipein;
|
||||
@@ -373,24 +288,14 @@ int ScriptController::Execute()
|
||||
|
||||
#ifdef WIN32
|
||||
// build command line
|
||||
|
||||
char* szCmdLine = NULL;
|
||||
if (m_szArgs)
|
||||
char szCmdLine[2048];
|
||||
int iUsedLen = 0;
|
||||
for (const char** szArgPtr = m_szArgs; *szArgPtr; szArgPtr++)
|
||||
{
|
||||
char szCmdLineBuf[2048];
|
||||
int iUsedLen = 0;
|
||||
for (const char** szArgPtr = m_szArgs; *szArgPtr; szArgPtr++)
|
||||
{
|
||||
snprintf(szCmdLineBuf + iUsedLen, 2048 - iUsedLen, "\"%s\" ", *szArgPtr);
|
||||
iUsedLen += strlen(*szArgPtr) + 3;
|
||||
}
|
||||
szCmdLineBuf[iUsedLen < 2048 ? iUsedLen - 1 : 2048 - 1] = '\0';
|
||||
szCmdLine = szCmdLineBuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
szCmdLine = m_szCmdLine;
|
||||
snprintf(szCmdLine + iUsedLen, 2048 - iUsedLen, "\"%s\" ", *szArgPtr);
|
||||
iUsedLen += strlen(*szArgPtr) + 3;
|
||||
}
|
||||
szCmdLine[iUsedLen < 2048 ? iUsedLen - 1 : 2048 - 1] = '\0';
|
||||
|
||||
// create pipes to write and read data
|
||||
HANDLE hReadPipe, hWritePipe;
|
||||
@@ -605,7 +510,11 @@ int ScriptController::Execute()
|
||||
} // while (!bChildConfirmed && !m_bTerminated)
|
||||
#endif
|
||||
|
||||
debug("Exit code %i", iExitCode);
|
||||
if (!m_bTerminated)
|
||||
{
|
||||
info("Completed %s", m_szInfoName);
|
||||
debug("Exit code %i", iExitCode);
|
||||
}
|
||||
|
||||
return iExitCode;
|
||||
}
|
||||
@@ -650,7 +559,7 @@ void ScriptController::ProcessOutput(char* szText)
|
||||
|
||||
for (char* pend = szText + strlen(szText) - 1; pend >= szText && (*pend == '\n' || *pend == '\r' || *pend == ' '); pend--) *pend = '\0';
|
||||
|
||||
if (szText[0] == '\0')
|
||||
if (strlen(szText) == 0)
|
||||
{
|
||||
// skip empty lines
|
||||
return;
|
||||
@@ -658,54 +567,78 @@ void ScriptController::ProcessOutput(char* szText)
|
||||
|
||||
if (!strncmp(szText, "[INFO] ", 7))
|
||||
{
|
||||
PrintMessage(Message::mkInfo, szText + 7);
|
||||
AddMessage(Message::mkInfo, false, szText + 7);
|
||||
}
|
||||
else if (!strncmp(szText, "[WARNING] ", 10))
|
||||
{
|
||||
PrintMessage(Message::mkWarning, szText + 10);
|
||||
AddMessage(Message::mkWarning, false, szText + 10);
|
||||
}
|
||||
else if (!strncmp(szText, "[ERROR] ", 8))
|
||||
{
|
||||
PrintMessage(Message::mkError, szText + 8);
|
||||
AddMessage(Message::mkError, false, szText + 8);
|
||||
}
|
||||
else if (!strncmp(szText, "[DETAIL] ", 9))
|
||||
{
|
||||
PrintMessage(Message::mkDetail, szText + 9);
|
||||
AddMessage(Message::mkDetail, false, szText + 9);
|
||||
}
|
||||
else if (!strncmp(szText, "[DEBUG] ", 8))
|
||||
{
|
||||
PrintMessage(Message::mkDebug, szText + 8);
|
||||
AddMessage(Message::mkDebug, false, szText + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkInfo, szText);
|
||||
{
|
||||
switch (m_eDefaultLogKind)
|
||||
{
|
||||
case Options::slNone:
|
||||
break;
|
||||
|
||||
case Options::slDetail:
|
||||
AddMessage(Message::mkDetail, true, szText);
|
||||
break;
|
||||
|
||||
case Options::slInfo:
|
||||
AddMessage(Message::mkInfo, true, szText);
|
||||
break;
|
||||
|
||||
case Options::slWarning:
|
||||
AddMessage(Message::mkWarning, true, szText);
|
||||
break;
|
||||
|
||||
case Options::slError:
|
||||
AddMessage(Message::mkError, true, szText);
|
||||
break;
|
||||
|
||||
case Options::slDebug:
|
||||
AddMessage(Message::mkDebug, true, szText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug("Processing output received from script - completed");
|
||||
}
|
||||
|
||||
void ScriptController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
void ScriptController::AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText)
|
||||
{
|
||||
switch (eKind)
|
||||
{
|
||||
case Message::mkDetail:
|
||||
detail("%s", szText);
|
||||
detail("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkInfo:
|
||||
info("%s", szText);
|
||||
info("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkWarning:
|
||||
warn("%s", szText);
|
||||
warn("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkError:
|
||||
error("%s", szText);
|
||||
error("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkDebug:
|
||||
debug("%s", szText);
|
||||
debug("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -719,26 +652,18 @@ void ScriptController::PrintMessage(Message::EKind eKind, const char* szFormat,
|
||||
vsnprintf(tmp2, 1024, szFormat, ap);
|
||||
tmp2[1024-1] = '\0';
|
||||
va_end(ap);
|
||||
|
||||
char tmp3[1024];
|
||||
if (m_szLogPrefix)
|
||||
{
|
||||
snprintf(tmp3, 1024, "%s: %s", m_szLogPrefix, tmp2);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(tmp3, tmp2, 1024);
|
||||
}
|
||||
tmp3[1024-1] = '\0';
|
||||
|
||||
AddMessage(eKind, tmp3);
|
||||
|
||||
AddMessage(eKind, false, tmp2);
|
||||
}
|
||||
|
||||
void PostScriptController::StartJob(PostInfo* pPostInfo)
|
||||
void PostScriptController::StartScriptJob(PostInfo* pPostInfo, bool bNZBFileCompleted, bool bHasFailedParJobs)
|
||||
{
|
||||
PostScriptController* pScriptController = new PostScriptController();
|
||||
pScriptController->m_pPostInfo = pPostInfo;
|
||||
pScriptController->SetScript(g_pOptions->GetPostProcess());
|
||||
pScriptController->SetWorkingDir(g_pOptions->GetDestDir());
|
||||
pScriptController->m_bNZBFileCompleted = bNZBFileCompleted;
|
||||
pScriptController->m_bHasFailedParJobs = bHasFailedParJobs;
|
||||
pScriptController->SetAutoDestroy(false);
|
||||
|
||||
pPostInfo->SetPostThread(pScriptController);
|
||||
@@ -747,81 +672,6 @@ void PostScriptController::StartJob(PostInfo* pPostInfo)
|
||||
}
|
||||
|
||||
void PostScriptController::Run()
|
||||
{
|
||||
FileList activeList;
|
||||
|
||||
// the locking is needed for accessing the members of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
for (NZBParameterList::iterator it = m_pPostInfo->GetNZBInfo()->GetParameters()->begin(); it != m_pPostInfo->GetNZBInfo()->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 = strdup(szVarname);
|
||||
szScriptName[strlen(szScriptName)-1] = '\0'; // remove trailing ':'
|
||||
activeList.push_back(szScriptName);
|
||||
}
|
||||
}
|
||||
m_pPostInfo->GetNZBInfo()->GetScriptStatuses()->Clear();
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
|
||||
Options::ScriptList scriptList;
|
||||
g_pOptions->LoadScriptList(&scriptList);
|
||||
|
||||
for (Options::ScriptList::iterator it = scriptList.begin(); it != scriptList.end(); it++)
|
||||
{
|
||||
Options::Script* pScript = *it;
|
||||
for (FileList::iterator it2 = activeList.begin(); it2 != activeList.end(); it2++)
|
||||
{
|
||||
char* szActiveName = *it2;
|
||||
// if any script has requested par-check, do not execute other scripts
|
||||
if (Util::SameFilename(pScript->GetName(), szActiveName) && !m_pPostInfo->GetRequestParCheck())
|
||||
{
|
||||
ExecuteScript(pScript->GetName(), pScript->GetDisplayName(), pScript->GetLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (FileList::iterator it = activeList.begin(); it != activeList.end(); it++)
|
||||
{
|
||||
free(*it);
|
||||
}
|
||||
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
}
|
||||
|
||||
void PostScriptController::ExecuteScript(const char* szScriptName, const char* szDisplayName, const char* szLocation)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Executing post-process-script %s for %s", szScriptName, m_pPostInfo->GetInfoName());
|
||||
|
||||
SetScript(szLocation);
|
||||
SetArgs(NULL, false);
|
||||
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "post-process-script %s for %s", szScriptName, m_pPostInfo->GetInfoName());
|
||||
szInfoName[1024-1] = '\0';
|
||||
SetInfoName(szInfoName);
|
||||
|
||||
SetLogPrefix(szDisplayName);
|
||||
PrepareParams(szScriptName);
|
||||
|
||||
int iExitCode = Execute();
|
||||
|
||||
szInfoName[0] = 'P'; // uppercase
|
||||
|
||||
SetLogPrefix(NULL);
|
||||
ScriptStatus::EStatus eStatus = AnalyseExitCode(iExitCode);
|
||||
|
||||
// the locking is needed for accessing the members of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
m_pPostInfo->GetNZBInfo()->GetScriptStatuses()->Add(szScriptName, eStatus);
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
}
|
||||
|
||||
void PostScriptController::PrepareParams(const char* szScriptName)
|
||||
{
|
||||
// the locking is needed for accessing the members of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
@@ -830,105 +680,156 @@ void PostScriptController::PrepareParams(const char* szScriptName)
|
||||
strncpy(szNZBName, m_pPostInfo->GetNZBInfo()->GetName(), 1024);
|
||||
szNZBName[1024-1] = '\0';
|
||||
|
||||
int iParStatus[] = { 0, 0, 1, 2, 3, 4 };
|
||||
int iParStatus[] = { 0, 0, 1, 2, 3 };
|
||||
char szParStatus[10];
|
||||
snprintf(szParStatus, 10, "%i", iParStatus[m_pPostInfo->GetNZBInfo()->GetParStatus()]);
|
||||
snprintf(szParStatus, 10, "%i", iParStatus[g_pOptions->GetAllowReProcess() ? (int)m_pPostInfo->GetParStatus() : (int)m_pPostInfo->GetNZBInfo()->GetParStatus()]);
|
||||
szParStatus[10-1] = '\0';
|
||||
|
||||
int iUnpackStatus[] = { 0, 0, 1, 2 };
|
||||
char szUnpackStatus[10];
|
||||
snprintf(szUnpackStatus, 10, "%i", iUnpackStatus[m_pPostInfo->GetNZBInfo()->GetUnpackStatus()]);
|
||||
snprintf(szUnpackStatus, 10, "%i", g_pOptions->GetAllowReProcess() ? 0 : iUnpackStatus[m_pPostInfo->GetNZBInfo()->GetUnpackStatus()]);
|
||||
szUnpackStatus[10-1] = '\0';
|
||||
|
||||
char szCollectionCompleted[10];
|
||||
snprintf(szCollectionCompleted, 10, "%i", (int)m_bNZBFileCompleted);
|
||||
szCollectionCompleted[10-1] = '\0';
|
||||
|
||||
char szHasFailedParJobs[10];
|
||||
snprintf(szHasFailedParJobs, 10, "%i", (int)m_bHasFailedParJobs);
|
||||
szHasFailedParJobs[10-1] = '\0';
|
||||
|
||||
char szDestDir[1024];
|
||||
strncpy(szDestDir, m_pPostInfo->GetNZBInfo()->GetDestDir(), 1024);
|
||||
szDestDir[1024-1] = '\0';
|
||||
|
||||
char szNZBID[10];
|
||||
snprintf(szNZBID, 10, "%i", m_pPostInfo->GetNZBInfo()->GetID());
|
||||
szNZBID[10-1] = '\0';
|
||||
|
||||
char szNZBFilename[1024];
|
||||
strncpy(szNZBFilename, m_pPostInfo->GetNZBInfo()->GetFilename(), 1024);
|
||||
szNZBFilename[1024-1] = '\0';
|
||||
|
||||
char szParFilename[1024];
|
||||
strncpy(szParFilename, m_pPostInfo->GetParFilename(), 1024);
|
||||
szParFilename[1024-1] = '\0';
|
||||
|
||||
char szCategory[1024];
|
||||
strncpy(szCategory, m_pPostInfo->GetNZBInfo()->GetCategory(), 1024);
|
||||
szCategory[1024-1] = '\0';
|
||||
|
||||
// Reset
|
||||
ResetEnv();
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "post-process-script for %s", g_pOptions->GetAllowReProcess() ? m_pPostInfo->GetInfoName() : m_pPostInfo->GetNZBInfo()->GetName());
|
||||
szInfoName[1024-1] = '\0';
|
||||
SetInfoName(szInfoName);
|
||||
|
||||
SetDefaultKindPrefix("Post-Process: ");
|
||||
SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
const char* szArgs[9];
|
||||
szArgs[0] = GetScript();
|
||||
szArgs[1] = szDestDir;
|
||||
szArgs[2] = szNZBFilename;
|
||||
szArgs[3] = szParFilename;
|
||||
szArgs[4] = szParStatus;
|
||||
szArgs[5] = szCollectionCompleted;
|
||||
szArgs[6] = szHasFailedParJobs;
|
||||
szArgs[7] = szCategory;
|
||||
szArgs[8] = NULL;
|
||||
SetArgs(szArgs, false);
|
||||
|
||||
SetEnvVar("NZBPP_NZBNAME", szNZBName);
|
||||
SetEnvVar("NZBPP_NZBID", szNZBID);
|
||||
SetEnvVar("NZBPP_DIRECTORY", szDestDir);
|
||||
SetEnvVar("NZBPP_NZBFILENAME", szNZBFilename);
|
||||
SetEnvVar("NZBPP_PARFILENAME", szParFilename);
|
||||
SetEnvVar("NZBPP_PARSTATUS", szParStatus);
|
||||
SetEnvVar("NZBPP_UNPACKSTATUS", szUnpackStatus);
|
||||
SetEnvVar("NZBPP_NZBCOMPLETED", szCollectionCompleted);
|
||||
SetEnvVar("NZBPP_PARFAILED", szHasFailedParJobs);
|
||||
SetEnvVar("NZBPP_CATEGORY", szCategory);
|
||||
|
||||
PrepareEnvParameters(m_pPostInfo->GetNZBInfo(), NULL);
|
||||
PrepareEnvParameters(m_pPostInfo->GetNZBInfo());
|
||||
|
||||
char szParamPrefix[1024];
|
||||
snprintf(szParamPrefix, 1024, "%s:", szScriptName);
|
||||
szParamPrefix[1024-1] = '\0';
|
||||
PrepareEnvParameters(m_pPostInfo->GetNZBInfo(), szParamPrefix);
|
||||
PrepareEnvOptions(szParamPrefix);
|
||||
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
}
|
||||
|
||||
ScriptStatus::EStatus PostScriptController::AnalyseExitCode(int iExitCode)
|
||||
{
|
||||
// The ScriptStatus is accumulated for all scripts:
|
||||
// If any script has failed the status is "failure", etc.
|
||||
info("Executing post-process-script for %s", g_pOptions->GetAllowReProcess() ? m_pPostInfo->GetInfoName() : szNZBName);
|
||||
|
||||
switch (iExitCode)
|
||||
int iResult = Execute();
|
||||
|
||||
szInfoName[0] = 'P'; // uppercase
|
||||
|
||||
switch (iResult)
|
||||
{
|
||||
case POSTPROCESS_SUCCESS:
|
||||
PrintMessage(Message::mkInfo, "%s successful", GetInfoName());
|
||||
return ScriptStatus::srSuccess;
|
||||
info("%s successful", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srSuccess);
|
||||
break;
|
||||
|
||||
case POSTPROCESS_ERROR:
|
||||
case -1: // Execute() returns -1 if the process could not be started (file not found or other problem)
|
||||
PrintMessage(Message::mkError, "%s failed", GetInfoName());
|
||||
return ScriptStatus::srFailure;
|
||||
info("%s failed", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srFailure);
|
||||
break;
|
||||
|
||||
case POSTPROCESS_NONE:
|
||||
PrintMessage(Message::mkInfo, "%s skipped", GetInfoName());
|
||||
return ScriptStatus::srNone;
|
||||
info("%s skipped", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srNone);
|
||||
break;
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
case POSTPROCESS_PARCHECK:
|
||||
if (m_pPostInfo->GetNZBInfo()->GetParStatus() > NZBInfo::psSkipped)
|
||||
case POSTPROCESS_PARCHECK_ALL:
|
||||
if (m_pPostInfo->GetParStatus() > PostInfo::psSkipped)
|
||||
{
|
||||
PrintMessage(Message::mkError, "%s requested par-check/repair, but the collection was already checked", GetInfoName());
|
||||
return ScriptStatus::srFailure;
|
||||
error("%s requested par-check/repair for all collections, but they were already checked", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srFailure);
|
||||
}
|
||||
else if (!m_bNZBFileCompleted)
|
||||
{
|
||||
error("%s requested par-check/repair for all collections, but it was not the call for the last collection", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srFailure);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "%s requested par-check/repair", GetInfoName());
|
||||
m_pPostInfo->SetRequestParCheck(true);
|
||||
return ScriptStatus::srSuccess;
|
||||
info("%s requested par-check/repair for all collections", szInfoName);
|
||||
m_pPostInfo->SetRequestParCheck(PostInfo::rpAll);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srSuccess);
|
||||
}
|
||||
break;
|
||||
|
||||
case POSTPROCESS_PARCHECK_CURRENT:
|
||||
if (m_pPostInfo->GetParStatus() > PostInfo::psSkipped)
|
||||
{
|
||||
error("%s requested par-check/repair for current collection, but it was already checked", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srFailure);
|
||||
}
|
||||
else if (strlen(m_pPostInfo->GetParFilename()) == 0)
|
||||
{
|
||||
error("%s requested par-check/repair for current collection, but it doesn't have any par-files", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srFailure);
|
||||
}
|
||||
else
|
||||
{
|
||||
info("%s requested par-check/repair for current collection", szInfoName);
|
||||
m_pPostInfo->SetRequestParCheck(PostInfo::rpCurrent);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srSuccess);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
PrintMessage(Message::mkError, "%s failed (terminated with unknown status)", GetInfoName());
|
||||
return ScriptStatus::srFailure;
|
||||
info("%s terminated with unknown status", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srUnknown);
|
||||
}
|
||||
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
}
|
||||
|
||||
void PostScriptController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
void PostScriptController::AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText)
|
||||
{
|
||||
if (!strncmp(szText, "[HISTORY] ", 10))
|
||||
{
|
||||
m_pPostInfo->GetNZBInfo()->AppendMessage(eKind, 0, szText);
|
||||
m_pPostInfo->GetNZBInfo()->AppendMessage(eKind, 0, szText + 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptController::AddMessage(eKind, szText);
|
||||
ScriptController::AddMessage(eKind, bDefaultKind, szText);
|
||||
m_pPostInfo->AppendMessage(eKind, szText);
|
||||
}
|
||||
|
||||
@@ -967,59 +868,16 @@ void PostScriptController::Stop()
|
||||
Terminate();
|
||||
}
|
||||
|
||||
/**
|
||||
* DownloadQueue must be locked prior to call of this function.
|
||||
*/
|
||||
void PostScriptController::InitParamsForNewNZB(NZBInfo* pNZBInfo)
|
||||
{
|
||||
const char* szDefScript = g_pOptions->GetDefScript();
|
||||
|
||||
if (pNZBInfo->GetCategory() && strlen(pNZBInfo->GetCategory()) > 0)
|
||||
{
|
||||
Options::Category* pCategory = g_pOptions->FindCategory(pNZBInfo->GetCategory());
|
||||
if (pCategory && pCategory->GetDefScript() && strlen(pCategory->GetDefScript()) > 0)
|
||||
{
|
||||
szDefScript = pCategory->GetDefScript();
|
||||
}
|
||||
}
|
||||
|
||||
if (!szDefScript || strlen(szDefScript) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// split szDefScript into tokens and create pp-parameter for each token
|
||||
char* szDefScript2 = strdup(szDefScript);
|
||||
char* saveptr;
|
||||
char* szScriptName = strtok_r(szDefScript2, ",;", &saveptr);
|
||||
while (szScriptName)
|
||||
{
|
||||
szScriptName = Util::Trim(szScriptName);
|
||||
if (szScriptName[0] != '\0')
|
||||
{
|
||||
char szParam[1024];
|
||||
snprintf(szParam, 1024, "%s:", szScriptName);
|
||||
szParam[1024-1] = '\0';
|
||||
pNZBInfo->GetParameters()->SetParameter(szParam, "yes");
|
||||
}
|
||||
szScriptName = strtok_r(NULL, ",;", &saveptr);
|
||||
}
|
||||
free(szDefScript2);
|
||||
}
|
||||
|
||||
void NZBScriptController::ExecuteScript(const char* szScript, const char* szNZBFilename, const char* szDirectory,
|
||||
char** pNZBName, char** pCategory, int* iPriority, NZBParameterList* pParameters, bool* bAddTop, bool* bAddPaused)
|
||||
void NZBScriptController::ExecuteScript(const char* szScript, const char* szNZBFilename,
|
||||
const char* szDirectory, char** pCategory, int* iPriority, NZBParameterList* pParameterList)
|
||||
{
|
||||
info("Executing nzb-process-script for %s", Util::BaseFileName(szNZBFilename));
|
||||
|
||||
NZBScriptController* pScriptController = new NZBScriptController();
|
||||
pScriptController->SetScript(szScript);
|
||||
pScriptController->m_pNZBName = pNZBName;
|
||||
pScriptController->m_pCategory = pCategory;
|
||||
pScriptController->m_pParameters = pParameters;
|
||||
pScriptController->m_pParameterList = pParameterList;
|
||||
pScriptController->m_iPriority = iPriority;
|
||||
pScriptController->m_bAddTop = bAddTop;
|
||||
pScriptController->m_bAddPaused = bAddPaused;
|
||||
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "nzb-process-script for %s", Util::BaseFileName(szNZBFilename));
|
||||
@@ -1036,51 +894,30 @@ void NZBScriptController::ExecuteScript(const char* szScript, const char* szNZBF
|
||||
szDir[iLen-1] = '\0';
|
||||
}
|
||||
|
||||
char szPriority[20];
|
||||
snprintf(szPriority, 20, "%i", *iPriority);
|
||||
szPriority[20-1] = '\0';
|
||||
pScriptController->SetDefaultKindPrefix("NZB-Process: ");
|
||||
pScriptController->SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
char szAddTop[10];
|
||||
snprintf(szAddTop, 10, "%i", *bAddTop ? 1 : 0);
|
||||
szAddTop[10-1] = '\0';
|
||||
|
||||
char szAddPaused[10];
|
||||
snprintf(szAddPaused, 10, "%i", *bAddPaused ? 1 : 0);
|
||||
szAddPaused[10-1] = '\0';
|
||||
|
||||
char szLogPrefix[1024];
|
||||
strncpy(szLogPrefix, Util::BaseFileName(szScript), 1024);
|
||||
szLogPrefix[1024-1] = '\0';
|
||||
if (char* ext = strrchr(szLogPrefix, '.')) *ext = '\0'; // strip file extension
|
||||
pScriptController->SetLogPrefix(szLogPrefix);
|
||||
pScriptController->m_iPrefixLen = strlen(szLogPrefix) + 2; // 2 = strlen(": ");
|
||||
const char* szArgs[4];
|
||||
szArgs[0] = szScript;
|
||||
szArgs[1] = szDir;
|
||||
szArgs[2] = szNZBFilename;
|
||||
szArgs[3] = NULL;
|
||||
pScriptController->SetArgs(szArgs, false);
|
||||
|
||||
pScriptController->SetEnvVar("NZBNP_DIRECTORY", szDir);
|
||||
pScriptController->SetEnvVar("NZBNP_FILENAME", szNZBFilename);
|
||||
pScriptController->SetEnvVar("NZBNP_NZBNAME", strlen(*pNZBName) > 0 ? *pNZBName : Util::BaseFileName(szNZBFilename));
|
||||
pScriptController->SetEnvVar("NZBNP_CATEGORY", *pCategory);
|
||||
pScriptController->SetEnvVar("NZBNP_PRIORITY", szPriority);
|
||||
pScriptController->SetEnvVar("NZBNP_TOP", szAddTop);
|
||||
pScriptController->SetEnvVar("NZBNP_PAUSED", szAddPaused);
|
||||
|
||||
pScriptController->Execute();
|
||||
|
||||
delete pScriptController;
|
||||
}
|
||||
|
||||
void NZBScriptController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
void NZBScriptController::AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText)
|
||||
{
|
||||
szText = szText + m_iPrefixLen;
|
||||
|
||||
if (!strncmp(szText, "[NZB] ", 6))
|
||||
{
|
||||
debug("Command %s detected", szText + 6);
|
||||
if (!strncmp(szText + 6, "NZBNAME=", 8))
|
||||
{
|
||||
free(*m_pNZBName);
|
||||
*m_pNZBName = strdup(szText + 6 + 8);
|
||||
}
|
||||
else if (!strncmp(szText + 6, "CATEGORY=", 9))
|
||||
if (!strncmp(szText + 6, "CATEGORY=", 9))
|
||||
{
|
||||
free(*m_pCategory);
|
||||
*m_pCategory = strdup(szText + 6 + 9);
|
||||
@@ -1092,7 +929,7 @@ void NZBScriptController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
if (szValue)
|
||||
{
|
||||
*szValue = '\0';
|
||||
m_pParameters->SetParameter(szParam, szValue + 1);
|
||||
m_pParameterList->SetParameter(szParam, szValue + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1104,14 +941,6 @@ void NZBScriptController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
{
|
||||
*m_iPriority = atoi(szText + 6 + 9);
|
||||
}
|
||||
else if (!strncmp(szText + 6, "TOP=", 4))
|
||||
{
|
||||
*m_bAddTop = atoi(szText + 6 + 4) != 0;
|
||||
}
|
||||
else if (!strncmp(szText + 6, "PAUSED=", 7))
|
||||
{
|
||||
*m_bAddPaused = atoi(szText + 6 + 7) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Invalid command \"%s\" received from %s", szText, GetInfoName());
|
||||
@@ -1119,7 +948,7 @@ void NZBScriptController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptController::AddMessage(eKind, szText);
|
||||
ScriptController::AddMessage(eKind, bDefaultKind, szText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1128,8 +957,6 @@ void NZBAddedScriptController::StartScript(DownloadQueue* pDownloadQueue, NZBInf
|
||||
NZBAddedScriptController* pScriptController = new NZBAddedScriptController();
|
||||
pScriptController->SetScript(szScript);
|
||||
pScriptController->m_szNZBName = strdup(pNZBInfo->GetName());
|
||||
pScriptController->SetEnvVar("NZBNA_NZBNAME", pNZBInfo->GetName());
|
||||
// "NZBNA_NAME" is not correct but kept for compatibility with older versions where this name was used by mistake
|
||||
pScriptController->SetEnvVar("NZBNA_NAME", pNZBInfo->GetName());
|
||||
pScriptController->SetEnvVar("NZBNA_FILENAME", pNZBInfo->GetFilename());
|
||||
pScriptController->SetEnvVar("NZBNA_CATEGORY", pNZBInfo->GetCategory());
|
||||
@@ -1158,7 +985,7 @@ void NZBAddedScriptController::StartScript(DownloadQueue* pDownloadQueue, NZBInf
|
||||
snprintf(buf, 100, "%i", iMaxPriority);
|
||||
pScriptController->SetEnvVar("NZBNA_PRIORITY", buf);
|
||||
|
||||
pScriptController->PrepareEnvParameters(pNZBInfo, NULL);
|
||||
pScriptController->PrepareEnvParameters(pNZBInfo);
|
||||
|
||||
pScriptController->SetAutoDestroy(true);
|
||||
|
||||
@@ -1174,11 +1001,13 @@ void NZBAddedScriptController::Run()
|
||||
|
||||
info("Executing %s", szInfoName);
|
||||
|
||||
char szLogPrefix[1024];
|
||||
strncpy(szLogPrefix, Util::BaseFileName(GetScript()), 1024);
|
||||
szLogPrefix[1024-1] = '\0';
|
||||
if (char* ext = strrchr(szLogPrefix, '.')) *ext = '\0'; // strip file extension
|
||||
SetLogPrefix(szLogPrefix);
|
||||
SetDefaultKindPrefix("NZB-Added Process: ");
|
||||
SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
const char* szArgs[2];
|
||||
szArgs[0] = GetScript();
|
||||
szArgs[1] = NULL;
|
||||
SetArgs(szArgs, false);
|
||||
|
||||
Execute();
|
||||
|
||||
@@ -1211,11 +1040,8 @@ void SchedulerScriptController::Run()
|
||||
szInfoName[1024-1] = '\0';
|
||||
SetInfoName(szInfoName);
|
||||
|
||||
char szLogPrefix[1024];
|
||||
strncpy(szLogPrefix, Util::BaseFileName(GetScript()), 1024);
|
||||
szLogPrefix[1024-1] = '\0';
|
||||
if (char* ext = strrchr(szLogPrefix, '.')) *ext = '\0'; // strip file extension
|
||||
SetLogPrefix(szLogPrefix);
|
||||
SetDefaultKindPrefix("Scheduled Process: ");
|
||||
SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
Execute();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define SCRIPTCONTROLLER_H
|
||||
|
||||
#include <list>
|
||||
#include <fstream>
|
||||
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
@@ -43,7 +44,6 @@ private:
|
||||
public:
|
||||
EnvironmentStrings();
|
||||
~EnvironmentStrings();
|
||||
void Clear();
|
||||
void InitFromCurrentProcess();
|
||||
void Append(char* szString);
|
||||
#ifdef WIN32
|
||||
@@ -60,28 +60,26 @@ private:
|
||||
const char* m_szWorkingDir;
|
||||
const char** m_szArgs;
|
||||
bool m_bFreeArgs;
|
||||
const char* m_szStdArgs[2];
|
||||
const char* m_szInfoName;
|
||||
const char* m_szLogPrefix;
|
||||
const char* m_szDefaultKindPrefix;
|
||||
EnvironmentStrings m_environmentStrings;
|
||||
Options::EScriptLogKind m_eDefaultLogKind;
|
||||
bool m_bTerminated;
|
||||
#ifdef WIN32
|
||||
HANDLE m_hProcess;
|
||||
char m_szCmdLine[2048];
|
||||
#else
|
||||
pid_t m_hProcess;
|
||||
#endif
|
||||
|
||||
void PrepareEnvOptions();
|
||||
|
||||
protected:
|
||||
void ProcessOutput(char* szText);
|
||||
virtual bool ReadLine(char* szBuf, int iBufSize, FILE* pStream);
|
||||
void PrintMessage(Message::EKind eKind, const char* szFormat, ...);
|
||||
virtual void AddMessage(Message::EKind eKind, const char* szText);
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText);
|
||||
bool GetTerminated() { return m_bTerminated; }
|
||||
void ResetEnv();
|
||||
void PrepareEnvOptions(const char* szStripPrefix);
|
||||
void PrepareEnvParameters(NZBInfo* pNZBInfo, const char* szStripPrefix);
|
||||
void PrepareArgs();
|
||||
void PrepareEnvParameters(NZBInfo* pNZBInfo);
|
||||
|
||||
public:
|
||||
ScriptController();
|
||||
@@ -95,51 +93,39 @@ public:
|
||||
void SetArgs(const char** szArgs, bool bFreeArgs) { m_szArgs = szArgs; m_bFreeArgs = bFreeArgs; }
|
||||
void SetInfoName(const char* szInfoName) { m_szInfoName = szInfoName; }
|
||||
const char* GetInfoName() { return m_szInfoName; }
|
||||
void SetLogPrefix(const char* szLogPrefix) { m_szLogPrefix = szLogPrefix; }
|
||||
void SetDefaultKindPrefix(const char* szDefaultKindPrefix) { m_szDefaultKindPrefix = szDefaultKindPrefix; }
|
||||
void SetDefaultLogKind(Options::EScriptLogKind eDefaultLogKind) { m_eDefaultLogKind = eDefaultLogKind; }
|
||||
void SetEnvVar(const char* szName, const char* szValue);
|
||||
void SetEnvVarSpecial(const char* szPrefix, const char* szName, const char* szValue);
|
||||
};
|
||||
|
||||
class PostScriptController : public Thread, public ScriptController
|
||||
{
|
||||
private:
|
||||
PostInfo* m_pPostInfo;
|
||||
char m_szNZBName[1024];
|
||||
|
||||
void ExecuteScript(const char* szScriptName, const char* szDisplayName, const char* szLocation);
|
||||
void PrepareParams(const char* szScriptName);
|
||||
ScriptStatus::EStatus AnalyseExitCode(int iExitCode);
|
||||
|
||||
typedef std::deque<char*> FileList;
|
||||
bool m_bNZBFileCompleted;
|
||||
bool m_bHasFailedParJobs;
|
||||
|
||||
protected:
|
||||
virtual void AddMessage(Message::EKind eKind, const char* szText);
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText);
|
||||
|
||||
public:
|
||||
virtual void Run();
|
||||
virtual void Stop();
|
||||
static void StartJob(PostInfo* pPostInfo);
|
||||
static void InitParamsForNewNZB(NZBInfo* pNZBInfo);
|
||||
static void StartScriptJob(PostInfo* pPostInfo, bool bNZBFileCompleted, bool bHasFailedParJobs);
|
||||
};
|
||||
|
||||
class NZBScriptController : public ScriptController
|
||||
{
|
||||
private:
|
||||
char** m_pNZBName;
|
||||
char** m_pCategory;
|
||||
int* m_iPriority;
|
||||
NZBParameterList* m_pParameters;
|
||||
bool* m_bAddTop;
|
||||
bool* m_bAddPaused;
|
||||
int m_iPrefixLen;
|
||||
NZBParameterList* m_pParameterList;
|
||||
|
||||
protected:
|
||||
virtual void AddMessage(Message::EKind eKind, const char* szText);
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText);
|
||||
|
||||
public:
|
||||
static void ExecuteScript(const char* szScript, const char* szNZBFilename, const char* szDirectory,
|
||||
char** pNZBName, char** pCategory, int* iPriority, NZBParameterList* pParameters,
|
||||
bool* bAddTop, bool* bAddPaused);
|
||||
static void ExecuteScript(const char* szScript, const char* szNZBFilename, const char* szDirectory, char** pCategory, int* iPriority, NZBParameterList* pParameterList);
|
||||
};
|
||||
|
||||
class NZBAddedScriptController : public Thread, public ScriptController
|
||||
|
||||
6
TLS.cpp
6
TLS.cpp
@@ -26,15 +26,16 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
|
||||
#ifdef WIN32
|
||||
#define SKIP_DEFAULT_WINDOWS_HEADERS
|
||||
#include "win32.h"
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
@@ -42,6 +43,7 @@
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
275
Unpack.cpp
275
Unpack.cpp
@@ -33,8 +33,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <fstream>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -77,7 +77,7 @@ UnpackController::~UnpackController()
|
||||
m_archiveFiles.Clear();
|
||||
}
|
||||
|
||||
void UnpackController::StartJob(PostInfo* pPostInfo)
|
||||
void UnpackController::StartUnpackJob(PostInfo* pPostInfo)
|
||||
{
|
||||
UnpackController* pUnpackController = new UnpackController();
|
||||
pUnpackController->m_pPostInfo = pPostInfo;
|
||||
@@ -125,13 +125,11 @@ void UnpackController::Run()
|
||||
|
||||
snprintf(m_szInfoNameUp, 1024, "Unpack for %s", m_szName); // first letter in upper case
|
||||
m_szInfoNameUp[1024-1] = '\0';
|
||||
|
||||
CheckStateFiles();
|
||||
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
if (bUnpack && m_bHasBrokenFiles && m_pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && m_bHasParFiles)
|
||||
if (bUnpack && HasBrokenFiles() && m_pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && HasParFiles())
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "%s has broken files", m_szName);
|
||||
info("%s has broken files", m_szName);
|
||||
RequestParCheck(false);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
return;
|
||||
@@ -140,15 +138,13 @@ void UnpackController::Run()
|
||||
|
||||
if (bUnpack)
|
||||
{
|
||||
bool bScanNonStdFiles = m_pPostInfo->GetNZBInfo()->GetRenameStatus() > NZBInfo::rsSkipped ||
|
||||
m_pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psSuccess ||
|
||||
!m_bHasParFiles;
|
||||
CheckArchiveFiles(bScanNonStdFiles);
|
||||
CheckArchiveFiles();
|
||||
}
|
||||
|
||||
if (bUnpack && (m_bHasRarFiles || m_bHasNonStdRarFiles || m_bHasSevenZipFiles || m_bHasSevenZipMultiFiles))
|
||||
if (bUnpack && (m_bHasRarFiles || m_bHasSevenZipFiles || m_bHasSevenZipMultiFiles))
|
||||
{
|
||||
SetInfoName(m_szInfoName);
|
||||
SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
SetWorkingDir(m_szDestDir);
|
||||
|
||||
PrintMessage(Message::mkInfo, "Unpacking %s", m_szName);
|
||||
@@ -158,7 +154,7 @@ void UnpackController::Run()
|
||||
m_bUnpackOK = true;
|
||||
m_bUnpackStartError = false;
|
||||
|
||||
if (m_bHasRarFiles || m_bHasNonStdRarFiles)
|
||||
if (m_bHasRarFiles)
|
||||
{
|
||||
ExecuteUnrar();
|
||||
}
|
||||
@@ -180,13 +176,14 @@ void UnpackController::Run()
|
||||
PrintMessage(Message::mkInfo, (bUnpack ? "Nothing to unpack for %s" : "Unpack for %s skipped"), m_szName);
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
if (bUnpack && m_pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && m_bHasParFiles)
|
||||
if (bUnpack && m_pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && HasParFiles())
|
||||
{
|
||||
RequestParCheck(m_pPostInfo->GetNZBInfo()->GetRenameStatus() <= NZBInfo::rsSkipped);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_pPostInfo->SetUnpackStatus(PostInfo::usSkipped);
|
||||
m_pPostInfo->GetNZBInfo()->SetUnpackStatus(NZBInfo::usSkipped);
|
||||
m_pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
}
|
||||
@@ -212,20 +209,19 @@ void UnpackController::ExecuteUnrar()
|
||||
szArgs[3] = szPasswordParam;
|
||||
}
|
||||
szArgs[4] = "-o+";
|
||||
szArgs[5] = m_bHasNonStdRarFiles ? "*.*" : "*.rar";
|
||||
szArgs[5] = "*.rar";
|
||||
szArgs[6] = m_szUnpackDir;
|
||||
szArgs[7] = NULL;
|
||||
SetArgs(szArgs, false);
|
||||
|
||||
SetScript(g_pOptions->GetUnrarCmd());
|
||||
SetLogPrefix("Unrar");
|
||||
SetDefaultKindPrefix("Unrar: ");
|
||||
|
||||
m_bAllOKMessageReceived = false;
|
||||
m_eUnpacker = upUnrar;
|
||||
|
||||
SetProgressLabel("");
|
||||
int iExitCode = Execute();
|
||||
SetLogPrefix(NULL);
|
||||
SetProgressLabel("");
|
||||
|
||||
m_bUnpackOK = iExitCode == 0 && m_bAllOKMessageReceived && !GetTerminated();
|
||||
@@ -266,15 +262,14 @@ void UnpackController::ExecuteSevenZip(bool bMultiVolumes)
|
||||
SetArgs(szArgs, false);
|
||||
|
||||
SetScript(g_pOptions->GetSevenZipCmd());
|
||||
SetDefaultKindPrefix("7-Zip: ");
|
||||
|
||||
m_bAllOKMessageReceived = false;
|
||||
m_eUnpacker = upSevenZip;
|
||||
|
||||
PrintMessage(Message::mkInfo, "Executing 7-Zip");
|
||||
SetLogPrefix("7-Zip");
|
||||
SetProgressLabel("");
|
||||
int iExitCode = Execute();
|
||||
SetLogPrefix(NULL);
|
||||
SetProgressLabel("");
|
||||
|
||||
m_bUnpackOK = iExitCode == 0 && m_bAllOKMessageReceived && !GetTerminated();
|
||||
@@ -293,6 +288,7 @@ void UnpackController::Completed()
|
||||
if (m_bUnpackOK && bCleanupSuccess)
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "%s %s", m_szInfoNameUp, "successful");
|
||||
m_pPostInfo->SetUnpackStatus(PostInfo::usSuccess);
|
||||
m_pPostInfo->GetNZBInfo()->SetUnpackStatus(NZBInfo::usSuccess);
|
||||
m_pPostInfo->GetNZBInfo()->SetUnpackCleanedUpDisk(m_bCleanedUpDisk);
|
||||
m_pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
@@ -300,7 +296,7 @@ void UnpackController::Completed()
|
||||
else
|
||||
{
|
||||
#ifndef DISABLE_PARCHECK
|
||||
if (!m_bUnpackOK && m_pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && !m_bUnpackStartError && !GetTerminated() && m_bHasParFiles)
|
||||
if (!m_bUnpackOK && m_pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && !m_bUnpackStartError && !GetTerminated() && HasParFiles())
|
||||
{
|
||||
RequestParCheck(false);
|
||||
}
|
||||
@@ -308,6 +304,7 @@ void UnpackController::Completed()
|
||||
#endif
|
||||
{
|
||||
PrintMessage(Message::mkError, "%s failed", m_szInfoNameUp);
|
||||
m_pPostInfo->SetUnpackStatus(PostInfo::usFailure);
|
||||
m_pPostInfo->GetNZBInfo()->SetUnpackStatus(NZBInfo::usFailure);
|
||||
m_pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
}
|
||||
@@ -324,30 +321,33 @@ void UnpackController::RequestParCheck(bool bRename)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pPostInfo->SetRequestParCheck(true);
|
||||
m_pPostInfo->SetRequestParCheck(PostInfo::rpAll);
|
||||
}
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UnpackController::CheckStateFiles()
|
||||
bool UnpackController::HasParFiles()
|
||||
{
|
||||
return ParCoordinator::FindMainPars(m_szDestDir, NULL);
|
||||
}
|
||||
|
||||
bool UnpackController::HasBrokenFiles()
|
||||
{
|
||||
char szBrokenLog[1024];
|
||||
snprintf(szBrokenLog, 1024, "%s%c%s", m_szDestDir, PATH_SEPARATOR, "_brokenlog.txt");
|
||||
szBrokenLog[1024-1] = '\0';
|
||||
m_bHasBrokenFiles = Util::FileExists(szBrokenLog);
|
||||
|
||||
m_bHasParFiles = ParCoordinator::FindMainPars(m_szDestDir, NULL);
|
||||
return Util::FileExists(szBrokenLog);
|
||||
}
|
||||
|
||||
void UnpackController::CreateUnpackDir()
|
||||
{
|
||||
m_bInterDir = strlen(g_pOptions->GetInterDir()) > 0 &&
|
||||
!strncmp(m_szDestDir, g_pOptions->GetInterDir(), strlen(g_pOptions->GetInterDir()));
|
||||
if (m_bInterDir)
|
||||
if (strlen(g_pOptions->GetInterDir()) > 0 &&
|
||||
!strncmp(m_szDestDir, g_pOptions->GetInterDir(), strlen(g_pOptions->GetInterDir())))
|
||||
{
|
||||
m_pPostInfo->GetNZBInfo()->BuildFinalDirName(m_szFinalDir, 1024);
|
||||
m_szFinalDir[1024-1] = '\0';
|
||||
Util::ForceDirectories(m_szFinalDir);
|
||||
snprintf(m_szUnpackDir, 1024, "%s%c%s", m_szFinalDir, PATH_SEPARATOR, "_unpack");
|
||||
}
|
||||
else
|
||||
@@ -355,24 +355,17 @@ void UnpackController::CreateUnpackDir()
|
||||
snprintf(m_szUnpackDir, 1024, "%s%c%s", m_szDestDir, PATH_SEPARATOR, "_unpack");
|
||||
}
|
||||
m_szUnpackDir[1024-1] = '\0';
|
||||
|
||||
char szErrBuf[1024];
|
||||
if (!Util::ForceDirectories(m_szUnpackDir, szErrBuf, sizeof(szErrBuf)))
|
||||
{
|
||||
error("Could not create directory %s: %s", m_szUnpackDir, szErrBuf);
|
||||
}
|
||||
Util::ForceDirectories(m_szUnpackDir);
|
||||
}
|
||||
|
||||
|
||||
void UnpackController::CheckArchiveFiles(bool bScanNonStdFiles)
|
||||
void UnpackController::CheckArchiveFiles()
|
||||
{
|
||||
m_bHasRarFiles = false;
|
||||
m_bHasNonStdRarFiles = false;
|
||||
m_bHasSevenZipFiles = false;
|
||||
m_bHasSevenZipMultiFiles = false;
|
||||
|
||||
RegEx regExRar(".*\\.rar$");
|
||||
RegEx regExRarMultiSeq(".*\\.(r|s)[0-9][0-9]$");
|
||||
RegEx regExSevenZip(".*\\.7z$");
|
||||
RegEx regExSevenZipMulti(".*\\.7z\\.[0-9]*$");
|
||||
|
||||
@@ -389,32 +382,14 @@ void UnpackController::CheckArchiveFiles(bool bScanNonStdFiles)
|
||||
{
|
||||
m_bHasRarFiles = true;
|
||||
}
|
||||
else if (regExSevenZip.Match(filename))
|
||||
if (regExSevenZip.Match(filename))
|
||||
{
|
||||
m_bHasSevenZipFiles = true;
|
||||
}
|
||||
else if (regExSevenZipMulti.Match(filename))
|
||||
if (regExSevenZipMulti.Match(filename))
|
||||
{
|
||||
m_bHasSevenZipMultiFiles = true;
|
||||
}
|
||||
else if (bScanNonStdFiles && !m_bHasNonStdRarFiles && !regExRarMultiSeq.Match(filename))
|
||||
{
|
||||
// Check if file has RAR signature
|
||||
char rarSignature[] = {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00};
|
||||
char fileSignature[7];
|
||||
|
||||
FILE* infile;
|
||||
infile = fopen(szFullFilename, "rb");
|
||||
if (infile)
|
||||
{
|
||||
int cnt = (int)fread(fileSignature, 1, sizeof(fileSignature), infile);
|
||||
fclose(infile);
|
||||
if (cnt == sizeof(fileSignature) && !strcmp(rarSignature, fileSignature))
|
||||
{
|
||||
m_bHasNonStdRarFiles = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -476,7 +451,7 @@ bool UnpackController::Cleanup()
|
||||
{
|
||||
char* szFilename = *it;
|
||||
|
||||
if (m_bInterDir || !extractedFiles.Exists(szFilename))
|
||||
if (!extractedFiles.Exists(szFilename))
|
||||
{
|
||||
char szFullFilename[1024];
|
||||
snprintf(szFullFilename, 1024, "%s%c%s", m_szDestDir, PATH_SEPARATOR, szFilename);
|
||||
@@ -505,7 +480,7 @@ bool UnpackController::Cleanup()
|
||||
szFullFilename[1024-1] = '\0';
|
||||
|
||||
if (strcmp(filename, ".") && strcmp(filename, "..") && !Util::DirectoryExists(szFullFilename)
|
||||
&& regExSevenZip.Match(filename) && (m_bInterDir || !extractedFiles.Exists(filename)))
|
||||
&& regExSevenZip.Match(filename) && !extractedFiles.Exists(filename))
|
||||
{
|
||||
PrintMessage(Message::mkInfo, "Deleting file %s", filename);
|
||||
|
||||
@@ -587,7 +562,7 @@ bool UnpackController::ReadLine(char* szBuf, int iBufSize, FILE* pStream)
|
||||
return i > 0;
|
||||
}
|
||||
|
||||
void UnpackController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
void UnpackController::AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText)
|
||||
{
|
||||
char szMsgText[1024];
|
||||
strncpy(szMsgText, szText, 1024);
|
||||
@@ -595,39 +570,31 @@ void UnpackController::AddMessage(Message::EKind eKind, const char* szText)
|
||||
|
||||
// Modify unrar messages for better readability:
|
||||
// remove the destination path part from message "Extracting file.xxx"
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szText, "Unrar: Extracting ", 19) &&
|
||||
!strncmp(szText + 19, m_szUnpackDir, strlen(m_szUnpackDir)))
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szText, "Extracting ", 12) &&
|
||||
!strncmp(szText + 12, m_szUnpackDir, strlen(m_szUnpackDir)))
|
||||
{
|
||||
snprintf(szMsgText, 1024, "Unrar: Extracting %s", szText + 19 + strlen(m_szUnpackDir) + 1);
|
||||
snprintf(szMsgText, 1024, "Extracting %s", szText + 12 + strlen(m_szUnpackDir) + 1);
|
||||
szMsgText[1024-1] = '\0';
|
||||
}
|
||||
|
||||
ScriptController::AddMessage(eKind, szMsgText);
|
||||
ScriptController::AddMessage(eKind, bDefaultKind, szMsgText);
|
||||
m_pPostInfo->AppendMessage(eKind, szMsgText);
|
||||
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szMsgText, "Unrar: UNRAR ", 6) &&
|
||||
strstr(szMsgText, " Copyright ") && strstr(szMsgText, " Alexander Roshal"))
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szMsgText, "Extracting ", 11))
|
||||
{
|
||||
// reset start time for a case if user uses unpack-script to do some things
|
||||
// (like sending Wake-On-Lan message) before executing unrar
|
||||
m_pPostInfo->SetStageTime(time(NULL));
|
||||
SetProgressLabel(szMsgText);
|
||||
}
|
||||
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szMsgText, "Unrar: Extracting ", 18))
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szText, "Extracting from ", 16))
|
||||
{
|
||||
SetProgressLabel(szMsgText + 7);
|
||||
}
|
||||
|
||||
if (m_eUnpacker == upUnrar && !strncmp(szText, "Unrar: Extracting from ", 23))
|
||||
{
|
||||
const char *szFilename = szText + 23;
|
||||
const char *szFilename = szText + 16;
|
||||
debug("Filename: %s", szFilename);
|
||||
m_archiveFiles.push_back(strdup(szFilename));
|
||||
SetProgressLabel(szText + 7);
|
||||
SetProgressLabel(szText);
|
||||
}
|
||||
|
||||
if ((m_eUnpacker == upUnrar && !strncmp(szText, "Unrar: All OK", 13)) ||
|
||||
(m_eUnpacker == upSevenZip && !strncmp(szText, "7-Zip: Everything is Ok", 23)))
|
||||
if ((m_eUnpacker == upUnrar && !strncmp(szText, "All OK", 6)) ||
|
||||
(m_eUnpacker == upSevenZip && !strncmp(szText, "Everything is Ok", 16)))
|
||||
{
|
||||
m_bAllOKMessageReceived = true;
|
||||
}
|
||||
@@ -648,7 +615,7 @@ void UnpackController::SetProgressLabel(const char* szProgressLabel)
|
||||
}
|
||||
|
||||
|
||||
void MoveController::StartJob(PostInfo* pPostInfo)
|
||||
void MoveController::StartMoveJob(PostInfo* pPostInfo)
|
||||
{
|
||||
MoveController* pMoveController = new MoveController();
|
||||
pMoveController->m_pPostInfo = pPostInfo;
|
||||
@@ -673,6 +640,9 @@ void MoveController::Run()
|
||||
szInfoName[1024-1] = '\0';
|
||||
SetInfoName(szInfoName);
|
||||
|
||||
SetDefaultKindPrefix("Move: ");
|
||||
SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
strncpy(m_szInterDir, m_pPostInfo->GetNZBInfo()->GetDestDir(), 1024);
|
||||
m_szInterDir[1024-1] = '\0';
|
||||
|
||||
@@ -708,14 +678,10 @@ void MoveController::Run()
|
||||
|
||||
bool MoveController::MoveFiles()
|
||||
{
|
||||
char szErrBuf[1024];
|
||||
if (!Util::ForceDirectories(m_szDestDir, szErrBuf, sizeof(szErrBuf)))
|
||||
{
|
||||
error("Could not create directory %s: %s", m_szDestDir, szErrBuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bOK = true;
|
||||
|
||||
bOK = Util::ForceDirectories(m_szDestDir);
|
||||
|
||||
DirBrowser dir(m_szInterDir);
|
||||
while (const char* filename = dir.Next())
|
||||
{
|
||||
@@ -751,138 +717,3 @@ bool MoveController::MoveFiles()
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
|
||||
void CleanupController::StartJob(PostInfo* pPostInfo)
|
||||
{
|
||||
CleanupController* pCleanupController = new CleanupController();
|
||||
pCleanupController->m_pPostInfo = pPostInfo;
|
||||
pCleanupController->SetAutoDestroy(false);
|
||||
|
||||
pPostInfo->SetPostThread(pCleanupController);
|
||||
|
||||
pCleanupController->Start();
|
||||
}
|
||||
|
||||
void CleanupController::Run()
|
||||
{
|
||||
// the locking is needed for accessing the members of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
|
||||
char szNZBName[1024];
|
||||
strncpy(szNZBName, m_pPostInfo->GetNZBInfo()->GetName(), 1024);
|
||||
szNZBName[1024-1] = '\0';
|
||||
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "cleanup for %s", m_pPostInfo->GetNZBInfo()->GetName());
|
||||
szInfoName[1024-1] = '\0';
|
||||
SetInfoName(szInfoName);
|
||||
|
||||
strncpy(m_szDestDir, m_pPostInfo->GetNZBInfo()->GetDestDir(), 1024);
|
||||
m_szDestDir[1024-1] = '\0';
|
||||
|
||||
bool bInterDir = strlen(g_pOptions->GetInterDir()) > 0 &&
|
||||
!strncmp(m_szDestDir, g_pOptions->GetInterDir(), strlen(g_pOptions->GetInterDir()));
|
||||
if (bInterDir)
|
||||
{
|
||||
m_pPostInfo->GetNZBInfo()->BuildFinalDirName(m_szFinalDir, 1024);
|
||||
m_szFinalDir[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
m_szFinalDir[0] = '\0';
|
||||
}
|
||||
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
|
||||
info("Cleaning up %s", szNZBName);
|
||||
|
||||
bool bDeleted = false;
|
||||
bool bOK = Cleanup(m_szDestDir, &bDeleted);
|
||||
|
||||
if (bOK && m_szFinalDir[0] != '\0')
|
||||
{
|
||||
bool bDeleted2 = false;
|
||||
bOK = Cleanup(m_szFinalDir, &bDeleted2);
|
||||
bDeleted = bDeleted || bDeleted2;
|
||||
}
|
||||
|
||||
szInfoName[0] = 'C'; // uppercase
|
||||
|
||||
if (bOK && bDeleted)
|
||||
{
|
||||
info("%s successful", szInfoName);
|
||||
m_pPostInfo->GetNZBInfo()->SetCleanupStatus(NZBInfo::csSuccess);
|
||||
}
|
||||
else if (bOK)
|
||||
{
|
||||
info("Nothing to cleanup for %s", szNZBName);
|
||||
m_pPostInfo->GetNZBInfo()->SetCleanupStatus(NZBInfo::csSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("%s failed", szInfoName);
|
||||
m_pPostInfo->GetNZBInfo()->SetCleanupStatus(NZBInfo::csFailure);
|
||||
}
|
||||
|
||||
m_pPostInfo->SetStage(PostInfo::ptQueued);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
}
|
||||
|
||||
bool CleanupController::Cleanup(const char* szDestDir, bool *bDeleted)
|
||||
{
|
||||
*bDeleted = false;
|
||||
bool bOK = true;
|
||||
|
||||
ExtList extList;
|
||||
|
||||
// split ExtCleanupDisk into tokens and create a list
|
||||
char* szExtCleanupDisk = strdup(g_pOptions->GetExtCleanupDisk());
|
||||
|
||||
char* saveptr;
|
||||
char* szExt = strtok_r(szExtCleanupDisk, ",; ", &saveptr);
|
||||
while (szExt)
|
||||
{
|
||||
extList.push_back(szExt);
|
||||
szExt = strtok_r(NULL, ",; ", &saveptr);
|
||||
}
|
||||
|
||||
DirBrowser dir(szDestDir);
|
||||
while (const char* filename = dir.Next())
|
||||
{
|
||||
// check file extension
|
||||
|
||||
int iFilenameLen = strlen(filename);
|
||||
bool bDeleteIt = false;
|
||||
for (ExtList::iterator it = extList.begin(); it != extList.end(); it++)
|
||||
{
|
||||
const char* szExt = *it;
|
||||
int iExtLen = strlen(szExt);
|
||||
if (iFilenameLen >= iExtLen && !strcasecmp(szExt, filename + iFilenameLen - iExtLen))
|
||||
{
|
||||
bDeleteIt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDeleteIt)
|
||||
{
|
||||
char szFullFilename[1024];
|
||||
snprintf(szFullFilename, 1024, "%s%c%s", szDestDir, PATH_SEPARATOR, filename);
|
||||
szFullFilename[1024-1] = '\0';
|
||||
|
||||
PrintMessage(Message::mkInfo, "Deleting file %s", filename);
|
||||
if (remove(szFullFilename) != 0)
|
||||
{
|
||||
PrintMessage(Message::mkError, "Could not delete file %s! Errcode: %i", szFullFilename, errno);
|
||||
bOK = false;
|
||||
}
|
||||
|
||||
*bDeleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
free(szExtCleanupDisk);
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
31
Unpack.h
31
Unpack.h
@@ -59,13 +59,9 @@ private:
|
||||
char m_szFinalDir[1024];
|
||||
char m_szUnpackDir[1024];
|
||||
char m_szPassword[1024];
|
||||
bool m_bInterDir;
|
||||
bool m_bAllOKMessageReceived;
|
||||
bool m_bNoFilesMessageReceived;
|
||||
bool m_bHasParFiles;
|
||||
bool m_bHasBrokenFiles;
|
||||
bool m_bHasRarFiles;
|
||||
bool m_bHasNonStdRarFiles;
|
||||
bool m_bHasSevenZipFiles;
|
||||
bool m_bHasSevenZipMultiFiles;
|
||||
bool m_bUnpackOK;
|
||||
@@ -76,14 +72,15 @@ private:
|
||||
|
||||
protected:
|
||||
virtual bool ReadLine(char* szBuf, int iBufSize, FILE* pStream);
|
||||
virtual void AddMessage(Message::EKind eKind, const char* szText);
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, const char* szText);
|
||||
void ExecuteUnrar();
|
||||
void ExecuteSevenZip(bool bMultiVolumes);
|
||||
void Completed();
|
||||
void CreateUnpackDir();
|
||||
bool Cleanup();
|
||||
void CheckStateFiles();
|
||||
void CheckArchiveFiles(bool bScanNonStdFiles);
|
||||
bool HasParFiles();
|
||||
bool HasBrokenFiles();
|
||||
void CheckArchiveFiles();
|
||||
void SetProgressLabel(const char* szProgressLabel);
|
||||
#ifndef DISABLE_PARCHECK
|
||||
void RequestParCheck(bool bRename);
|
||||
@@ -93,7 +90,7 @@ public:
|
||||
virtual ~UnpackController();
|
||||
virtual void Run();
|
||||
virtual void Stop();
|
||||
static void StartJob(PostInfo* pPostInfo);
|
||||
static void StartUnpackJob(PostInfo* pPostInfo);
|
||||
};
|
||||
|
||||
class MoveController : public Thread, public ScriptController
|
||||
@@ -107,23 +104,7 @@ private:
|
||||
|
||||
public:
|
||||
virtual void Run();
|
||||
static void StartJob(PostInfo* pPostInfo);
|
||||
};
|
||||
|
||||
class CleanupController : public Thread, public ScriptController
|
||||
{
|
||||
private:
|
||||
PostInfo* m_pPostInfo;
|
||||
char m_szDestDir[1024];
|
||||
char m_szFinalDir[1024];
|
||||
|
||||
bool Cleanup(const char* szDestDir, bool *bDeleted);
|
||||
|
||||
typedef std::deque<char*> ExtList;
|
||||
|
||||
public:
|
||||
virtual void Run();
|
||||
static void StartJob(PostInfo* pPostInfo);
|
||||
static void StartMoveJob(PostInfo* pPostInfo);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2012-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <sys/stat.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
@@ -49,13 +49,10 @@
|
||||
#include "Util.h"
|
||||
#include "NZBFile.h"
|
||||
#include "QueueCoordinator.h"
|
||||
#include "Scanner.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
extern DiskState* g_pDiskState;
|
||||
extern QueueCoordinator* g_pQueueCoordinator;
|
||||
extern Scanner* g_pScanner;
|
||||
|
||||
|
||||
UrlDownloader::UrlDownloader() : WebDownloader()
|
||||
{
|
||||
@@ -145,7 +142,7 @@ void UrlCoordinator::Run()
|
||||
bool bHasMoreUrls = GetNextUrl(pDownloadQueue, pUrlInfo);
|
||||
bool bUrlDownloadsRunning = !m_ActiveDownloads.empty();
|
||||
m_bHasMoreJobs = bHasMoreUrls || bUrlDownloadsRunning;
|
||||
if (bHasMoreUrls && !IsStopped())
|
||||
if (bHasMoreUrls && !IsStopped() && Thread::GetThreadCount() < g_pOptions->GetThreadLimit())
|
||||
{
|
||||
StartUrlDownload(pUrlInfo);
|
||||
}
|
||||
@@ -421,8 +418,38 @@ void UrlCoordinator::UrlCompleted(UrlDownloader* pUrlDownloader)
|
||||
|
||||
void UrlCoordinator::AddToNZBQueue(UrlInfo* pUrlInfo, const char* szTempFilename, const char* szOriginalFilename, const char* szOriginalCategory)
|
||||
{
|
||||
g_pScanner->AddExternalFile(
|
||||
pUrlInfo->GetNZBFilename() && strlen(pUrlInfo->GetNZBFilename()) > 0 ? pUrlInfo->GetNZBFilename() : szOriginalFilename,
|
||||
strlen(pUrlInfo->GetCategory()) > 0 ? pUrlInfo->GetCategory() : szOriginalCategory,
|
||||
pUrlInfo->GetPriority(), NULL, pUrlInfo->GetAddTop(), pUrlInfo->GetAddPaused(), szTempFilename, NULL, 0, false);
|
||||
}
|
||||
info("Queue downloaded collection %s", szOriginalFilename);
|
||||
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromFile(szTempFilename, pUrlInfo->GetCategory());
|
||||
if (pNZBFile)
|
||||
{
|
||||
pNZBFile->GetNZBInfo()->SetName(NULL);
|
||||
pNZBFile->GetNZBInfo()->SetFilename(pUrlInfo->GetNZBFilename() && strlen(pUrlInfo->GetNZBFilename()) > 0 ? pUrlInfo->GetNZBFilename() : szOriginalFilename);
|
||||
|
||||
if (strlen(pUrlInfo->GetCategory()) > 0)
|
||||
{
|
||||
pNZBFile->GetNZBInfo()->SetCategory(pUrlInfo->GetCategory());
|
||||
}
|
||||
else if (szOriginalCategory)
|
||||
{
|
||||
pNZBFile->GetNZBInfo()->SetCategory(szOriginalCategory);
|
||||
}
|
||||
|
||||
pNZBFile->GetNZBInfo()->BuildDestDirName();
|
||||
|
||||
for (NZBFile::FileInfos::iterator it = pNZBFile->GetFileInfos()->begin(); it != pNZBFile->GetFileInfos()->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
pFileInfo->SetPriority(pUrlInfo->GetPriority());
|
||||
pFileInfo->SetPaused(pUrlInfo->GetAddPaused());
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, pUrlInfo->GetAddTop());
|
||||
delete pNZBFile;
|
||||
info("Collection %s added to queue", szOriginalFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not add downloaded collection %s to queue", szOriginalFilename);
|
||||
}
|
||||
}
|
||||
252
Util.cpp
252
Util.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -140,7 +140,15 @@ int getopt(int argc, char *argv[], char *optstring)
|
||||
DirBrowser::DirBrowser(const char* szPath)
|
||||
{
|
||||
char szMask[MAX_PATH + 1];
|
||||
snprintf(szMask, MAX_PATH + 1, "%s%c*.*", szPath, (int)PATH_SEPARATOR);
|
||||
int len = strlen(szPath);
|
||||
if (szPath[len] == '\\' || szPath[len] == '/')
|
||||
{
|
||||
snprintf(szMask, MAX_PATH + 1, "%s*.*", szPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szMask, MAX_PATH + 1, "%s%c*.*", szPath, (int)PATH_SEPARATOR);
|
||||
}
|
||||
szMask[MAX_PATH] = '\0';
|
||||
m_hFile = _findfirst(szMask, &m_FindData);
|
||||
m_bFirst = true;
|
||||
@@ -203,36 +211,6 @@ const char* DirBrowser::Next()
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
StringBuilder::StringBuilder()
|
||||
{
|
||||
m_szBuffer = NULL;
|
||||
m_iBufferSize = 0;
|
||||
m_iUsedSize = 0;
|
||||
}
|
||||
|
||||
StringBuilder::~StringBuilder()
|
||||
{
|
||||
if (m_szBuffer)
|
||||
{
|
||||
free(m_szBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void StringBuilder::Append(const char* szStr)
|
||||
{
|
||||
int iPartLen = strlen(szStr);
|
||||
if (m_iUsedSize + iPartLen + 1 > m_iBufferSize)
|
||||
{
|
||||
m_iBufferSize += iPartLen + 10240;
|
||||
m_szBuffer = (char*)realloc(m_szBuffer, m_iBufferSize);
|
||||
}
|
||||
strcpy(m_szBuffer + m_iUsedSize, szStr);
|
||||
m_iUsedSize += iPartLen;
|
||||
m_szBuffer[m_iUsedSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
char Util::VersionRevisionBuf[40];
|
||||
|
||||
char* Util::BaseFileName(const char* filename)
|
||||
@@ -267,13 +245,9 @@ void Util::NormalizePathSeparators(char* szPath)
|
||||
}
|
||||
}
|
||||
|
||||
bool Util::ForceDirectories(const char* szPath, char* szErrBuf, int iBufSize)
|
||||
bool Util::ForceDirectories(const char* szPath)
|
||||
{
|
||||
*szErrBuf = '\0';
|
||||
char szSysErrStr[256];
|
||||
char szNormPath[1024];
|
||||
strncpy(szNormPath, szPath, 1024);
|
||||
szNormPath[1024-1] = '\0';
|
||||
char* szNormPath = strdup(szPath);
|
||||
NormalizePathSeparators(szNormPath);
|
||||
int iLen = strlen(szNormPath);
|
||||
if ((iLen > 0) && szNormPath[iLen-1] == PATH_SEPARATOR
|
||||
@@ -286,30 +260,15 @@ bool Util::ForceDirectories(const char* szPath, char* szErrBuf, int iBufSize)
|
||||
}
|
||||
|
||||
struct stat buffer;
|
||||
bool bOK = !stat(szNormPath, &buffer);
|
||||
if (!bOK && errno != ENOENT)
|
||||
{
|
||||
snprintf(szErrBuf, iBufSize, "could not read information for directory %s: errno %i, %s", szNormPath, errno, GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
szErrBuf[iBufSize-1] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bOK && !S_ISDIR(buffer.st_mode))
|
||||
{
|
||||
snprintf(szErrBuf, iBufSize, "path %s is not a directory", szNormPath);
|
||||
szErrBuf[iBufSize-1] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bOK = !stat(szNormPath, &buffer) && S_ISDIR(buffer.st_mode);
|
||||
if (!bOK
|
||||
#ifdef WIN32
|
||||
&& strlen(szNormPath) > 2
|
||||
#endif
|
||||
)
|
||||
{
|
||||
char szParentPath[1024];
|
||||
strncpy(szParentPath, szNormPath, 1024);
|
||||
szParentPath[1024-1] = '\0';
|
||||
char* szParentPath = strdup(szNormPath);
|
||||
bOK = true;
|
||||
char* p = (char*)strrchr(szParentPath, PATH_SEPARATOR);
|
||||
if (p)
|
||||
{
|
||||
@@ -323,35 +282,20 @@ bool Util::ForceDirectories(const char* szPath, char* szErrBuf, int iBufSize)
|
||||
{
|
||||
*p = '\0';
|
||||
}
|
||||
if (strlen(szParentPath) != strlen(szPath) && !ForceDirectories(szParentPath, szErrBuf, iBufSize))
|
||||
if (strlen(szParentPath) != strlen(szPath))
|
||||
{
|
||||
return false;
|
||||
bOK = ForceDirectories(szParentPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (mkdir(szNormPath, S_DIRMODE) != 0 && errno != EEXIST)
|
||||
if (bOK)
|
||||
{
|
||||
snprintf(szErrBuf, iBufSize, "could not create directory %s: %s", szNormPath, GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
szErrBuf[iBufSize-1] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stat(szNormPath, &buffer) != 0)
|
||||
{
|
||||
snprintf(szErrBuf, iBufSize, "could not read information for directory %s: %s", szNormPath, GetLastErrorMessage(szSysErrStr, sizeof(szSysErrStr)));
|
||||
szErrBuf[iBufSize-1] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(buffer.st_mode))
|
||||
{
|
||||
snprintf(szErrBuf, iBufSize, "path %s is not a directory", szNormPath);
|
||||
szErrBuf[iBufSize-1] = 0;
|
||||
return false;
|
||||
mkdir(szNormPath, S_DIRMODE);
|
||||
bOK = !stat(szNormPath, &buffer) && S_ISDIR(buffer.st_mode);
|
||||
}
|
||||
free(szParentPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
free(szNormPath);
|
||||
return bOK;
|
||||
}
|
||||
|
||||
bool Util::GetCurrentDirectory(char* szBuffer, int iBufSize)
|
||||
@@ -417,20 +361,6 @@ bool Util::LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBuff
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Util::SaveBufferIntoFile(const char* szFileName, const char* szBuffer, int iBufLen)
|
||||
{
|
||||
FILE* pFile = fopen(szFileName, "wb");
|
||||
if (!pFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int iWrittenBytes = fwrite(szBuffer, 1, iBufLen, pFile);
|
||||
fclose(pFile);
|
||||
|
||||
return iWrittenBytes = iBufLen;
|
||||
}
|
||||
|
||||
bool Util::CreateSparseFile(const char* szFilename, int iSize)
|
||||
{
|
||||
bool bOK = false;
|
||||
@@ -710,9 +640,14 @@ long long Util::FileSize(const char* szFilename)
|
||||
#ifdef WIN32
|
||||
struct _stat32i64 buffer;
|
||||
_stat32i64(szFilename, &buffer);
|
||||
#else
|
||||
#ifdef HAVE_STAT64
|
||||
struct stat64 buffer;
|
||||
stat64(szFilename, &buffer);
|
||||
#else
|
||||
struct stat buffer;
|
||||
stat(szFilename, &buffer);
|
||||
#endif
|
||||
#endif
|
||||
return buffer.st_size;
|
||||
}
|
||||
@@ -858,23 +793,6 @@ void Util::FormatFileSize(char * szBuffer, int iBufLen, long long lFileSize)
|
||||
szBuffer[iBufLen - 1] = '\0';
|
||||
}
|
||||
|
||||
bool Util::SameFilename(const char* szFilename1, const char* szFilename2)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return strcasecmp(szFilename1, szFilename2) == 0;
|
||||
#else
|
||||
return strcmp(szFilename1, szFilename2) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
char* Util::GetLastErrorMessage(char* szBuffer, int iBufLen)
|
||||
{
|
||||
szBuffer[0] = '\0';
|
||||
strerror_r(errno, szBuffer, iBufLen);
|
||||
szBuffer[iBufLen-1] = '\0';
|
||||
return szBuffer;
|
||||
}
|
||||
|
||||
void Util::InitVersionRevision()
|
||||
{
|
||||
#ifndef WIN32
|
||||
@@ -973,7 +891,7 @@ void Util::TrimRight(char* szStr)
|
||||
{
|
||||
int iLen = strlen(szStr);
|
||||
char ch = szStr[iLen-1];
|
||||
while (iLen > 0 && (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'))
|
||||
while (*szStr && (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'))
|
||||
{
|
||||
szStr[iLen-1] = 0;
|
||||
iLen--;
|
||||
@@ -981,34 +899,6 @@ void Util::TrimRight(char* szStr)
|
||||
}
|
||||
}
|
||||
|
||||
char* Util::Trim(char* szStr)
|
||||
{
|
||||
TrimRight(szStr);
|
||||
char ch = *szStr;
|
||||
while (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t')
|
||||
{
|
||||
szStr++;
|
||||
ch = *szStr;
|
||||
}
|
||||
return szStr;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
bool Util::RegReadStr(HKEY hKey, const char* szKeyName, const char* szValueName, char* szBuffer, int* iBufLen)
|
||||
{
|
||||
HKEY hSubKey;
|
||||
if (!RegOpenKeyEx(hKey, szKeyName, 0, KEY_READ, &hSubKey))
|
||||
{
|
||||
DWORD iRetBytes = *iBufLen;
|
||||
LONG iRet = RegQueryValueEx(hSubKey, szValueName, NULL, NULL, (LPBYTE)szBuffer, &iRetBytes);
|
||||
*iBufLen = iRetBytes;
|
||||
RegCloseKey(hSubKey);
|
||||
return iRet == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
unsigned int WebUtil::DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szOutputBuffer)
|
||||
{
|
||||
@@ -1070,9 +960,9 @@ char* WebUtil::XmlEncode(const char* raw)
|
||||
iReqSize += 6;
|
||||
break;
|
||||
default:
|
||||
if (ch < 0x20 || ch >= 0x80)
|
||||
if (ch >= 0x80)
|
||||
{
|
||||
iReqSize += 10;
|
||||
iReqSize += 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1110,51 +1000,10 @@ char* WebUtil::XmlEncode(const char* raw)
|
||||
output += 6;
|
||||
break;
|
||||
default:
|
||||
if (ch < 0x20 || ch > 0x80)
|
||||
if (ch >= 0x80)
|
||||
{
|
||||
unsigned int cp = ch;
|
||||
|
||||
// decode utf8
|
||||
if ((cp >> 5) == 0x6 && (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
// 2 bytes
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp = ((cp << 6) & 0x7ff) + (ch & 0x3f);
|
||||
}
|
||||
else if ((cp >> 4) == 0xe && (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
// 3 bytes
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp = ((cp << 12) & 0xffff) + ((ch << 6) & 0xfff);
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp += ch & 0x3f;
|
||||
}
|
||||
else if ((cp >> 3) == 0x1e && (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
// 4 bytes
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp = ((cp << 18) & 0x1fffff) + ((ch << 12) & 0x3ffff);
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp += (ch << 6) & 0xfff;
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp += ch & 0x3f;
|
||||
}
|
||||
|
||||
// accept only valid XML 1.0 characters
|
||||
if (cp == 0x9 || cp == 0xA || cp == 0xD ||
|
||||
(0x20 <= cp && cp <= 0xD7FF) ||
|
||||
(0xE000 <= cp && cp <= 0xFFFD) ||
|
||||
(0x10000 <= cp && cp <= 0x10FFFF))
|
||||
{
|
||||
sprintf(output, "&#x%06x;", cp);
|
||||
output += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
// replace invalid characters with dots
|
||||
sprintf(output, ".");
|
||||
output += 1;
|
||||
}
|
||||
sprintf(output, "&#%i;", ch);
|
||||
output += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1348,38 +1197,9 @@ char* WebUtil::JsonEncode(const char* raw)
|
||||
output += 2;
|
||||
break;
|
||||
default:
|
||||
if (ch < 0x20 || ch > 0x80)
|
||||
if (ch < 0x20 || ch >= 0x80)
|
||||
{
|
||||
unsigned int cp = ch;
|
||||
|
||||
// decode utf8
|
||||
if ((cp >> 5) == 0x6 && (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
// 2 bytes
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp = ((cp << 6) & 0x7ff) + (ch & 0x3f);
|
||||
}
|
||||
else if ((cp >> 4) == 0xe && (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
// 3 bytes
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp = ((cp << 12) & 0xffff) + ((ch << 6) & 0xfff);
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp += ch & 0x3f;
|
||||
}
|
||||
else if ((cp >> 3) == 0x1e && (p[1] & 0xc0) == 0x80)
|
||||
{
|
||||
// 4 bytes
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp = ((cp << 18) & 0x1fffff) + ((ch << 12) & 0x3ffff);
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp += (ch << 6) & 0xfff;
|
||||
if (!(ch = *++p)) goto BreakLoop; // read next char
|
||||
cp += ch & 0x3f;
|
||||
}
|
||||
|
||||
// we support only Unicode range U+0000-U+FFFF
|
||||
sprintf(output, "\\u%04x", cp <= 0xFFFF ? cp : '.');
|
||||
sprintf(output, "\\u%04x", ch);
|
||||
output += 6;
|
||||
}
|
||||
else
|
||||
|
||||
26
Util.h
26
Util.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -57,19 +57,6 @@ public:
|
||||
const char* Next();
|
||||
};
|
||||
|
||||
class StringBuilder
|
||||
{
|
||||
private:
|
||||
char* m_szBuffer;
|
||||
int m_iBufferSize;
|
||||
int m_iUsedSize;
|
||||
public:
|
||||
StringBuilder();
|
||||
~StringBuilder();
|
||||
void Append(const char* szStr);
|
||||
const char* GetBuffer() { return m_szBuffer; }
|
||||
};
|
||||
|
||||
class Util
|
||||
{
|
||||
public:
|
||||
@@ -77,7 +64,6 @@ public:
|
||||
static char* BaseFileName(const char* filename);
|
||||
static void NormalizePathSeparators(char* szPath);
|
||||
static bool LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength);
|
||||
static bool SaveBufferIntoFile(const char* szFileName, const char* szBuffer, int iBufLen);
|
||||
static bool CreateSparseFile(const char* szFilename, int iSize);
|
||||
static bool TruncateFile(const char* szFilename, int iSize);
|
||||
static void MakeValidFilename(char* szFilename, char cReplaceChar, bool bAllowSlashes);
|
||||
@@ -87,7 +73,7 @@ public:
|
||||
static bool CreateDirectory(const char* szDirFilename);
|
||||
static bool RemoveDirectory(const char* szDirFilename);
|
||||
static bool DeleteDirectoryWithContent(const char* szDirFilename);
|
||||
static bool ForceDirectories(const char* szPath, char* szErrBuf, int iBufSize);
|
||||
static bool ForceDirectories(const char* szPath);
|
||||
static bool GetCurrentDirectory(char* szBuffer, int iBufSize);
|
||||
static bool SetCurrentDirectory(const char* szDirFilename);
|
||||
static long long FileSize(const char* szFilename);
|
||||
@@ -99,8 +85,6 @@ public:
|
||||
#endif
|
||||
static void ExpandFileName(const char* szFilename, char* szBuffer, int iBufSize);
|
||||
static void FormatFileSize(char* szBuffer, int iBufLen, long long lFileSize);
|
||||
static bool SameFilename(const char* szFilename1, const char* szFilename2);
|
||||
static char* GetLastErrorMessage(char* szBuffer, int iBufLen);
|
||||
|
||||
/*
|
||||
* Split command line int arguments.
|
||||
@@ -128,12 +112,6 @@ public:
|
||||
|
||||
static void TrimRight(char* szStr);
|
||||
|
||||
static char* Trim(char* szStr);
|
||||
|
||||
#ifdef WIN32
|
||||
static bool RegReadStr(HKEY hKey, const char* szKeyName, const char* szValueName, char* szBuffer, int* iBufLen);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns program version and revision number as string formatted like "0.7.0-r295".
|
||||
* If revision number is not available only version is returned ("0.7.0").
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2012-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2012-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -107,7 +107,7 @@ void WebProcessor::Execute()
|
||||
char* szAuthInfo64 = p + 21;
|
||||
if (strlen(szAuthInfo64) > sizeof(szAuthInfo))
|
||||
{
|
||||
error("Invalid-request: auth-info too big");
|
||||
error("invalid-request: auth-info too big");
|
||||
return;
|
||||
}
|
||||
szAuthInfo[WebUtil::DecodeBase64(szAuthInfo64, 0, szAuthInfo)] = '\0';
|
||||
@@ -131,7 +131,7 @@ void WebProcessor::Execute()
|
||||
|
||||
if (m_eHttpMethod == hmPost && iContentLen <= 0)
|
||||
{
|
||||
error("Invalid-request: content length is 0");
|
||||
error("invalid-request: content length is 0");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -185,25 +185,20 @@ void WebProcessor::Execute()
|
||||
|
||||
debug("Final URL=%s", m_szUrl);
|
||||
|
||||
if (strlen(g_pOptions->GetControlPassword()) > 0)
|
||||
if (strlen(szAuthInfo) == 0)
|
||||
{
|
||||
if (strlen(szAuthInfo) == 0)
|
||||
{
|
||||
SendAuthResponse();
|
||||
return;
|
||||
}
|
||||
SendAuthResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
// Authorization
|
||||
char* pw = strchr(szAuthInfo, ':');
|
||||
if (pw) *pw++ = '\0';
|
||||
if ((strlen(g_pOptions->GetControlUsername()) > 0 && strcmp(szAuthInfo, g_pOptions->GetControlUsername())) ||
|
||||
strcmp(pw, g_pOptions->GetControlPassword()))
|
||||
{
|
||||
warn("Request received on port %i from %s, but username or password invalid (%s:%s)",
|
||||
g_pOptions->GetControlPort(), m_pConnection->GetRemoteAddr(), szAuthInfo, pw);
|
||||
SendAuthResponse();
|
||||
return;
|
||||
}
|
||||
// Authorization
|
||||
char* pw = strchr(szAuthInfo, ':');
|
||||
if (pw) *pw++ = '\0';
|
||||
if (strcmp(szAuthInfo, "nzbget") || strcmp(pw, g_pOptions->GetControlPassword()))
|
||||
{
|
||||
warn("request received on port %i from %s, but password invalid", g_pOptions->GetControlPort(), m_pConnection->GetRemoteAddr());
|
||||
SendAuthResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eHttpMethod == hmPost)
|
||||
@@ -214,7 +209,8 @@ void WebProcessor::Execute()
|
||||
|
||||
if (!m_pConnection->Recv(m_szRequest, iContentLen))
|
||||
{
|
||||
error("Invalid-request: could not read data");
|
||||
free(m_szRequest);
|
||||
error("invalid-request: could not read data");
|
||||
return;
|
||||
}
|
||||
debug("Request=%s", m_szRequest);
|
||||
|
||||
277
XmlRpc.cpp
277
XmlRpc.cpp
@@ -33,7 +33,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <stdarg.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
@@ -47,17 +48,45 @@
|
||||
#include "UrlCoordinator.h"
|
||||
#include "QueueEditor.h"
|
||||
#include "PrePostProcessor.h"
|
||||
#include "Scanner.h"
|
||||
#include "Util.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
extern QueueCoordinator* g_pQueueCoordinator;
|
||||
extern UrlCoordinator* g_pUrlCoordinator;
|
||||
extern PrePostProcessor* g_pPrePostProcessor;
|
||||
extern Scanner* g_pScanner;
|
||||
extern void ExitProc();
|
||||
extern void Reload();
|
||||
|
||||
//*****************************************************************
|
||||
// StringBuilder
|
||||
|
||||
StringBuilder::StringBuilder()
|
||||
{
|
||||
m_szBuffer = NULL;
|
||||
m_iBufferSize = 0;
|
||||
m_iUsedSize = 0;
|
||||
}
|
||||
|
||||
StringBuilder::~StringBuilder()
|
||||
{
|
||||
if (m_szBuffer)
|
||||
{
|
||||
free(m_szBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void StringBuilder::Append(const char* szStr)
|
||||
{
|
||||
int iPartLen = strlen(szStr);
|
||||
if (m_iUsedSize + iPartLen + 1 > m_iBufferSize)
|
||||
{
|
||||
m_iBufferSize += iPartLen + 10240;
|
||||
m_szBuffer = (char*)realloc(m_szBuffer, m_iBufferSize);
|
||||
}
|
||||
strcpy(m_szBuffer + m_iUsedSize, szStr);
|
||||
m_iUsedSize += iPartLen;
|
||||
m_szBuffer[m_iUsedSize] = '\0';
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
// XmlRpcProcessor
|
||||
@@ -414,10 +443,6 @@ XmlCommand* XmlRpcProcessor::CreateCommand(const char* szMethodName)
|
||||
{
|
||||
command = new SaveConfigXmlCommand();
|
||||
}
|
||||
else if (!strcasecmp(szMethodName, "configtemplates"))
|
||||
{
|
||||
command = new ConfigTemplatesXmlCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
command = new ErrorXmlCommand(1, "Invalid procedure");
|
||||
@@ -1354,7 +1379,6 @@ EditCommandEntry EditCommandNameMap[] = {
|
||||
{ QueueEditor::eaFilePauseExtraPars, "FilePauseExtraPars" },
|
||||
{ QueueEditor::eaFileSetPriority, "FileSetPriority" },
|
||||
{ QueueEditor::eaFileReorder, "FileReorder" },
|
||||
{ QueueEditor::eaFileSplit, "FileSplit" },
|
||||
{ QueueEditor::eaGroupMoveOffset, "GroupMoveOffset" },
|
||||
{ QueueEditor::eaGroupMoveTop, "GroupMoveTop" },
|
||||
{ QueueEditor::eaGroupMoveBottom, "GroupMoveBottom" },
|
||||
@@ -1375,7 +1399,6 @@ EditCommandEntry EditCommandNameMap[] = {
|
||||
{ PrePostProcessor::eaHistoryDelete, "HistoryDelete" },
|
||||
{ PrePostProcessor::eaHistoryReturn, "HistoryReturn" },
|
||||
{ PrePostProcessor::eaHistoryProcess, "HistoryProcess" },
|
||||
{ PrePostProcessor::eaHistorySetParameter, "HistorySetParameter" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
@@ -1442,7 +1465,7 @@ void EditQueueXmlCommand::Execute()
|
||||
}
|
||||
else
|
||||
{
|
||||
bOK = g_pPrePostProcessor->QueueEditList(&cIDList, (PrePostProcessor::EEditAction)iAction, iOffset, szEditText);
|
||||
bOK = g_pPrePostProcessor->QueueEditList(&cIDList, (PrePostProcessor::EEditAction)iAction, iOffset);
|
||||
}
|
||||
|
||||
BuildBoolResponse(bOK);
|
||||
@@ -1504,10 +1527,26 @@ void DownloadXmlCommand::Execute()
|
||||
szFileContent[iLen] = '\0';
|
||||
//debug("FileContent=%s", szFileContent);
|
||||
|
||||
bool bOK = g_pScanner->AddExternalFile(szFileName, szCategory, iPriority, NULL, bAddTop,
|
||||
false, NULL, szFileContent, iLen, true);
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromBuffer(szFileName, szCategory, szFileContent, iLen + 1);
|
||||
|
||||
BuildBoolResponse(bOK);
|
||||
if (pNZBFile)
|
||||
{
|
||||
info("Request: Queue collection %s", szFileName);
|
||||
|
||||
for (NZBFile::FileInfos::iterator it = pNZBFile->GetFileInfos()->begin(); it != pNZBFile->GetFileInfos()->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
pFileInfo->SetPriority(iPriority);
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, bAddTop);
|
||||
delete pNZBFile;
|
||||
BuildBoolResponse(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildBoolResponse(false);
|
||||
}
|
||||
}
|
||||
|
||||
void PostQueueXmlCommand::Execute()
|
||||
@@ -1525,7 +1564,7 @@ void PostQueueXmlCommand::Execute()
|
||||
"<member><name>NZBNicename</name><value><string>%s</string></value></member>\n" // deprecated, use "NZBName" instead
|
||||
"<member><name>NZBFilename</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>DestDir</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>ParFilename</name><value><string>%s</string></value></member>\n" // deprecated, always empty
|
||||
"<member><name>ParFilename</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>InfoName</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>Stage</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>ProgressLabel</name><value><string>%s</string></value></member>\n"
|
||||
@@ -1547,7 +1586,7 @@ void PostQueueXmlCommand::Execute()
|
||||
"\"NZBNicename\" : \"%s\",\n" // deprecated, use "NZBName" instead
|
||||
"\"NZBFilename\" : \"%s\",\n"
|
||||
"\"DestDir\" : \"%s\",\n"
|
||||
"\"ParFilename\" : \"%s\",\n" // deprecated, always empty
|
||||
"\"ParFilename\" : \"%s\",\n"
|
||||
"\"InfoName\" : \"%s\",\n"
|
||||
"\"Stage\" : \"%s\",\n"
|
||||
"\"ProgressLabel\" : \"%s\",\n"
|
||||
@@ -1595,12 +1634,13 @@ void PostQueueXmlCommand::Execute()
|
||||
char* xmlNZBNicename = EncodeStr(pPostInfo->GetNZBInfo()->GetName());
|
||||
char* xmlNZBFilename = EncodeStr(pPostInfo->GetNZBInfo()->GetFilename());
|
||||
char* xmlDestDir = EncodeStr(pPostInfo->GetNZBInfo()->GetDestDir());
|
||||
char* xmlParFilename = EncodeStr(pPostInfo->GetParFilename());
|
||||
char* xmlInfoName = EncodeStr(pPostInfo->GetInfoName());
|
||||
char* xmlProgressLabel = EncodeStr(pPostInfo->GetProgressLabel());
|
||||
|
||||
snprintf(szItemBuf, szItemBufSize, IsJson() ? JSON_POSTQUEUE_ITEM_START : XML_POSTQUEUE_ITEM_START,
|
||||
pPostInfo->GetID(), pPostInfo->GetNZBInfo()->GetID(), xmlNZBNicename,
|
||||
xmlNZBNicename, xmlNZBFilename, xmlDestDir, "",
|
||||
xmlNZBNicename, xmlNZBFilename, xmlDestDir, xmlParFilename,
|
||||
xmlInfoName, szPostStageName[pPostInfo->GetStage()], xmlProgressLabel,
|
||||
pPostInfo->GetFileProgress(), pPostInfo->GetStageProgress(),
|
||||
pPostInfo->GetStartTime() ? tCurTime - pPostInfo->GetStartTime() : 0,
|
||||
@@ -1610,6 +1650,7 @@ void PostQueueXmlCommand::Execute()
|
||||
free(xmlNZBNicename);
|
||||
free(xmlNZBFilename);
|
||||
free(xmlDestDir);
|
||||
free(xmlParFilename);
|
||||
free(xmlInfoName);
|
||||
free(xmlProgressLabel);
|
||||
|
||||
@@ -1725,7 +1766,7 @@ void ScanXmlCommand::Execute()
|
||||
// optional parameter "SyncMode"
|
||||
NextParamAsBool(&bSyncMode);
|
||||
|
||||
g_pScanner->ScanNZBDir(bSyncMode);
|
||||
g_pPrePostProcessor->ScanNZBDir(bSyncMode);
|
||||
BuildBoolResponse(true);
|
||||
}
|
||||
|
||||
@@ -1736,7 +1777,7 @@ void HistoryXmlCommand::Execute()
|
||||
const char* XML_HISTORY_ITEM_START =
|
||||
"<value><struct>\n"
|
||||
"<member><name>ID</name><value><i4>%i</i4></value></member>\n"
|
||||
"<member><name>NZBID</name><value><i4>%i</i4></value></member>\n"
|
||||
"<member><name>NZBID</name><value><i4>%i</i4></value></member>\n" // deprecated, use ID instead
|
||||
"<member><name>Kind</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>Name</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>NZBNicename</name><value><string>%s</string></value></member>\n" // deprecated, use Name instead
|
||||
@@ -1757,24 +1798,20 @@ void HistoryXmlCommand::Execute()
|
||||
"<member><name>UrlStatus</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>Parameters</name><value><array><data>\n";
|
||||
|
||||
const char* XML_HISTORY_ITEM_SCRIPT_START =
|
||||
"</data></array></value></member>\n"
|
||||
"<member><name>ScriptStatuses</name><value><array><data>\n";
|
||||
|
||||
const char* XML_HISTORY_ITEM_LOG_START =
|
||||
const char* XML_HISTORY_ITEM_LOG_START =
|
||||
"</data></array></value></member>\n"
|
||||
"<member><name>Log</name><value><array><data>\n";
|
||||
|
||||
const char* XML_HISTORY_ITEM_END =
|
||||
const char* XML_HISTORY_ITEM_END =
|
||||
"</data></array></value></member>\n"
|
||||
"</struct></value>\n";
|
||||
|
||||
const char* JSON_HISTORY_ITEM_START =
|
||||
"{\n"
|
||||
"\"ID\" : %i,\n"
|
||||
"\"NZBID\" : %i,\n"
|
||||
"\"NZBID\" : %i,\n" // deprecated, use ID instead
|
||||
"\"Kind\" : \"%s\",\n"
|
||||
"\"Name\" : \"%s\",\n"
|
||||
"\"Name\" : \"%s\",\n" // deprecated, use Name instead
|
||||
"\"NZBNicename\" : \"%s\",\n" // deprecated, use Name instead
|
||||
"\"NZBFilename\" : \"%s\",\n"
|
||||
"\"DestDir\" : \"%s\",\n"
|
||||
@@ -1793,11 +1830,7 @@ void HistoryXmlCommand::Execute()
|
||||
"\"UrlStatus\" : \"%s\",\n"
|
||||
"\"Parameters\" : [\n";
|
||||
|
||||
const char* JSON_HISTORY_ITEM_SCRIPT_START =
|
||||
"],\n"
|
||||
"\"ScriptStatuses\" : [\n";
|
||||
|
||||
const char* JSON_HISTORY_ITEM_LOG_START =
|
||||
const char* JSON_HISTORY_ITEM_LOG_START =
|
||||
"],\n"
|
||||
"\"Log\" : [\n";
|
||||
|
||||
@@ -1817,19 +1850,7 @@ void HistoryXmlCommand::Execute()
|
||||
"\"Value\" : \"%s\"\n"
|
||||
"}";
|
||||
|
||||
const char* XML_SCRIPT_ITEM =
|
||||
"<value><struct>\n"
|
||||
"<member><name>Name</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>Status</name><value><string>%s</string></value></member>\n"
|
||||
"</struct></value>\n";
|
||||
|
||||
const char* JSON_SCRIPT_ITEM =
|
||||
"{\n"
|
||||
"\"Name\" : \"%s\",\n"
|
||||
"\"Status\" : \"%s\"\n"
|
||||
"}";
|
||||
|
||||
const char* XML_LOG_ITEM =
|
||||
const char* XML_LOG_ITEM =
|
||||
"<value><struct>\n"
|
||||
"<member><name>ID</name><value><i4>%i</i4></value></member>\n"
|
||||
"<member><name>Kind</name><value><string>%s</string></value></member>\n"
|
||||
@@ -1845,10 +1866,10 @@ void HistoryXmlCommand::Execute()
|
||||
"\"Text\" : \"%s\"\n"
|
||||
"}";
|
||||
|
||||
const char* szParStatusName[] = { "NONE", "NONE", "FAILURE", "SUCCESS", "REPAIR_POSSIBLE", "MANUAL" };
|
||||
const char* szParStatusName[] = { "NONE", "NONE", "FAILURE", "SUCCESS", "REPAIR_POSSIBLE" };
|
||||
const char* szUnpackStatusName[] = { "NONE", "NONE", "FAILURE", "SUCCESS" };
|
||||
const char* szMoveStatusName[] = { "NONE", "FAILURE", "SUCCESS" };
|
||||
const char* szScriptStatusName[] = { "NONE", "FAILURE", "SUCCESS" };
|
||||
const char* szScriptStatusName[] = { "NONE", "UNKNOWN", "FAILURE", "SUCCESS" };
|
||||
const char* szUrlStatusName[] = { "UNKNOWN", "UNKNOWN", "SUCCESS", "FAILURE", "UNKNOWN" };
|
||||
const char* szMessageType[] = { "INFO", "WARNING", "ERROR", "DEBUG", "DETAIL"};
|
||||
|
||||
@@ -1882,10 +1903,10 @@ void HistoryXmlCommand::Execute()
|
||||
xmlCategory = EncodeStr(pNZBInfo->GetCategory());
|
||||
|
||||
snprintf(szItemBuf, szItemBufSize, IsJson() ? JSON_HISTORY_ITEM_START : XML_HISTORY_ITEM_START,
|
||||
pHistoryInfo->GetID(), pNZBInfo->GetID(), "NZB", xmlNicename, xmlNicename, xmlNZBFilename,
|
||||
pHistoryInfo->GetID(), pHistoryInfo->GetID(), "NZB", xmlNicename, xmlNicename, xmlNZBFilename,
|
||||
xmlDestDir, xmlCategory, szParStatusName[pNZBInfo->GetParStatus()],
|
||||
szUnpackStatusName[pNZBInfo->GetUnpackStatus()], szMoveStatusName[pNZBInfo->GetMoveStatus()],
|
||||
szScriptStatusName[pNZBInfo->GetScriptStatuses()->CalcTotalStatus()],
|
||||
szScriptStatusName[pNZBInfo->GetScriptStatus()],
|
||||
iFileSizeLo, iFileSizeHi, iFileSizeMB, pNZBInfo->GetFileCount(),
|
||||
pNZBInfo->GetParkedFileCount(), pHistoryInfo->GetTime(), "", "");
|
||||
|
||||
@@ -1900,7 +1921,7 @@ void HistoryXmlCommand::Execute()
|
||||
char* xmlURL = EncodeStr(pUrlInfo->GetURL());
|
||||
|
||||
snprintf(szItemBuf, szItemBufSize, IsJson() ? JSON_HISTORY_ITEM_START : XML_HISTORY_ITEM_START,
|
||||
pHistoryInfo->GetID(), 0, "URL", xmlNicename, xmlNicename, xmlNZBFilename,
|
||||
pHistoryInfo->GetID(), pHistoryInfo->GetID(), "URL", xmlNicename, xmlNicename, xmlNZBFilename,
|
||||
"", xmlCategory, "", "", "", "", 0, 0, 0, 0, 0, pHistoryInfo->GetTime(), xmlURL,
|
||||
szUrlStatusName[pUrlInfo->GetStatus()]);
|
||||
|
||||
@@ -1944,33 +1965,6 @@ void HistoryXmlCommand::Execute()
|
||||
}
|
||||
}
|
||||
|
||||
AppendResponse(IsJson() ? JSON_HISTORY_ITEM_SCRIPT_START : XML_HISTORY_ITEM_SCRIPT_START);
|
||||
|
||||
if (pNZBInfo)
|
||||
{
|
||||
// Script statuses
|
||||
int iScriptIndex = 0;
|
||||
for (ScriptStatusList::iterator it = pNZBInfo->GetScriptStatuses()->begin(); it != pNZBInfo->GetScriptStatuses()->end(); it++)
|
||||
{
|
||||
ScriptStatus* pScriptStatus = *it;
|
||||
|
||||
char* xmlName = EncodeStr(pScriptStatus->GetName());
|
||||
char* xmlStatus = EncodeStr(szScriptStatusName[pScriptStatus->GetStatus()]);
|
||||
|
||||
snprintf(szItemBuf, szItemBufSize, IsJson() ? JSON_SCRIPT_ITEM : XML_SCRIPT_ITEM, xmlName, xmlStatus);
|
||||
szItemBuf[szItemBufSize-1] = '\0';
|
||||
|
||||
free(xmlName);
|
||||
free(xmlStatus);
|
||||
|
||||
if (IsJson() && iScriptIndex++ > 0)
|
||||
{
|
||||
AppendResponse(",\n");
|
||||
}
|
||||
AppendResponse(szItemBuf);
|
||||
}
|
||||
}
|
||||
|
||||
AppendResponse(IsJson() ? JSON_HISTORY_ITEM_LOG_START : XML_HISTORY_ITEM_LOG_START);
|
||||
|
||||
if (pNZBInfo)
|
||||
@@ -2065,7 +2059,7 @@ void DownloadUrlXmlCommand::Execute()
|
||||
|
||||
char szNicename[1024];
|
||||
pUrlInfo->GetName(szNicename, sizeof(szNicename));
|
||||
info("Queue %s", szNicename);
|
||||
info("Request: Queue %s", szNicename);
|
||||
|
||||
g_pUrlCoordinator->AddUrlToQueue(pUrlInfo, bAddTop);
|
||||
|
||||
@@ -2193,7 +2187,7 @@ void ConfigXmlCommand::Execute()
|
||||
AppendResponse(IsJson() ? "\n]" : "</data></array>\n");
|
||||
}
|
||||
|
||||
// struct[] loadconfig()
|
||||
// struct[] loadconfig(string domain)
|
||||
void LoadConfigXmlCommand::Execute()
|
||||
{
|
||||
const char* XML_CONFIG_ITEM =
|
||||
@@ -2208,10 +2202,36 @@ void LoadConfigXmlCommand::Execute()
|
||||
"\"Value\" : \"%s\"\n"
|
||||
"}";
|
||||
|
||||
Options::OptEntries* pOptEntries = new Options::OptEntries();
|
||||
if (!g_pOptions->LoadConfig(pOptEntries))
|
||||
char* szDomain;
|
||||
if (!NextParamAsStr(&szDomain))
|
||||
{
|
||||
BuildErrorResponse(3, "Could not read configuration file");
|
||||
BuildErrorResponse(2, "Invalid parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* szConfigFile = NULL;
|
||||
Options::EDomain eDomain;
|
||||
|
||||
if (!strcasecmp(szDomain, "SERVER"))
|
||||
{
|
||||
eDomain = Options::dmServer;
|
||||
szConfigFile = g_pOptions->GetConfigFilename();
|
||||
}
|
||||
else if (!strcasecmp(szDomain, "POST"))
|
||||
{
|
||||
eDomain = Options::dmPostProcess;
|
||||
szConfigFile = g_pOptions->GetPostConfigFilename();
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildErrorResponse(2, "Invalid parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
Options::OptEntries* pOptEntries = new Options::OptEntries();
|
||||
if (!g_pOptions->LoadConfig(eDomain, pOptEntries))
|
||||
{
|
||||
BuildErrorResponse(3, "Could not read configuration file %s", szConfigFile);
|
||||
delete pOptEntries;
|
||||
return;
|
||||
}
|
||||
@@ -2249,9 +2269,38 @@ void LoadConfigXmlCommand::Execute()
|
||||
AppendResponse(IsJson() ? "\n]" : "</data></array>\n");
|
||||
}
|
||||
|
||||
// bool saveconfig(struct[] data)
|
||||
// bool saveconfig(string domain, struct[] data)
|
||||
void SaveConfigXmlCommand::Execute()
|
||||
{
|
||||
char* szDomain;
|
||||
if (!NextParamAsStr(&szDomain))
|
||||
{
|
||||
BuildErrorResponse(2, "Invalid parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
Options::EDomain eDomain;
|
||||
|
||||
if (!strcasecmp(szDomain, "SERVER"))
|
||||
{
|
||||
eDomain = Options::dmServer;
|
||||
}
|
||||
else if (!strcasecmp(szDomain, "POST"))
|
||||
{
|
||||
eDomain = Options::dmPostProcess;
|
||||
const char* szConfigFile = g_pOptions->GetPostConfigFilename();
|
||||
if (!szConfigFile)
|
||||
{
|
||||
BuildErrorResponse(3, "Post-processing script configuration file is not defined");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildErrorResponse(2, "Invalid parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
Options::OptEntries* pOptEntries = new Options::OptEntries();
|
||||
|
||||
char* szName;
|
||||
@@ -2265,71 +2314,9 @@ void SaveConfigXmlCommand::Execute()
|
||||
}
|
||||
|
||||
// save to config file
|
||||
bool bOK = g_pOptions->SaveConfig(pOptEntries);
|
||||
bool bOK = g_pOptions->SaveConfig(eDomain, pOptEntries);
|
||||
|
||||
delete pOptEntries;
|
||||
|
||||
BuildBoolResponse(bOK);
|
||||
}
|
||||
|
||||
// struct[] configtemplates()
|
||||
void ConfigTemplatesXmlCommand::Execute()
|
||||
{
|
||||
const char* XML_CONFIG_ITEM =
|
||||
"<value><struct>\n"
|
||||
"<member><name>Name</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>DisplayName</name><value><string>%s</string></value></member>\n"
|
||||
"<member><name>Template</name><value><string>%s</string></value></member>\n"
|
||||
"</struct></value>\n";
|
||||
|
||||
const char* JSON_CONFIG_ITEM =
|
||||
"{\n"
|
||||
"\"Name\" : \"%s\",\n"
|
||||
"\"DisplayName\" : \"%s\",\n"
|
||||
"\"Template\" : \"%s\"\n"
|
||||
"}";
|
||||
|
||||
Options::ConfigTemplates* pConfigTemplates = new Options::ConfigTemplates();
|
||||
|
||||
if (!g_pOptions->LoadConfigTemplates(pConfigTemplates))
|
||||
{
|
||||
BuildErrorResponse(3, "Could not read configuration templates");
|
||||
delete pConfigTemplates;
|
||||
return;
|
||||
}
|
||||
|
||||
AppendResponse(IsJson() ? "[\n" : "<array><data>\n");
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (Options::ConfigTemplates::iterator it = pConfigTemplates->begin(); it != pConfigTemplates->end(); it++)
|
||||
{
|
||||
Options::ConfigTemplate* pConfigTemplate = *it;
|
||||
|
||||
char* xmlName = EncodeStr(pConfigTemplate->GetName());
|
||||
char* xmlDisplayName = EncodeStr(pConfigTemplate->GetDisplayName());
|
||||
char* xmlTemplate = EncodeStr(pConfigTemplate->GetTemplate());
|
||||
|
||||
int szItemBufSize = strlen(xmlName) + strlen(xmlTemplate) + 1024;
|
||||
char* szItemBuf = (char*)malloc(szItemBufSize);
|
||||
|
||||
snprintf(szItemBuf, szItemBufSize, IsJson() ? JSON_CONFIG_ITEM : XML_CONFIG_ITEM, xmlName, xmlDisplayName, xmlTemplate);
|
||||
szItemBuf[szItemBufSize-1] = '\0';
|
||||
|
||||
free(xmlName);
|
||||
free(xmlDisplayName);
|
||||
free(xmlTemplate);
|
||||
|
||||
if (IsJson() && index++ > 0)
|
||||
{
|
||||
AppendResponse(",\n");
|
||||
}
|
||||
AppendResponse(szItemBuf);
|
||||
|
||||
free(szItemBuf);
|
||||
}
|
||||
|
||||
delete pConfigTemplates;
|
||||
|
||||
AppendResponse(IsJson() ? "\n]" : "</data></array>\n");
|
||||
}
|
||||
|
||||
21
XmlRpc.h
21
XmlRpc.h
@@ -27,7 +27,19 @@
|
||||
#define XMLRPC_H
|
||||
|
||||
#include "Connection.h"
|
||||
#include "Util.h"
|
||||
|
||||
class StringBuilder
|
||||
{
|
||||
private:
|
||||
char* m_szBuffer;
|
||||
int m_iBufferSize;
|
||||
int m_iUsedSize;
|
||||
public:
|
||||
StringBuilder();
|
||||
~StringBuilder();
|
||||
void Append(const char* szStr);
|
||||
const char* GetBuffer() { return m_szBuffer; }
|
||||
};
|
||||
|
||||
class XmlCommand;
|
||||
|
||||
@@ -270,12 +282,7 @@ class SaveConfigXmlCommand: public XmlCommand
|
||||
{
|
||||
public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class ConfigTemplatesXmlCommand: public XmlCommand
|
||||
{
|
||||
public:
|
||||
virtual void Execute();
|
||||
void Save(const char *szFilename);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,6 +79,9 @@
|
||||
/* Define to 1 if spinlocks are supported */
|
||||
#undef HAVE_SPINLOCK
|
||||
|
||||
/* Define to 1 if stat64 is supported */
|
||||
#undef HAVE_STAT64
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
@@ -135,9 +138,3 @@
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
400
configure
vendored
400
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.61 for nzbget 11.0-testing.
|
||||
# Generated by GNU Autoconf 2.61 for nzbget 10.2.
|
||||
#
|
||||
# Report bugs to <hugbug@users.sourceforge.net>.
|
||||
#
|
||||
@@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='nzbget'
|
||||
PACKAGE_TARNAME='nzbget'
|
||||
PACKAGE_VERSION='11.0-testing'
|
||||
PACKAGE_STRING='nzbget 11.0-testing'
|
||||
PACKAGE_VERSION='10.2'
|
||||
PACKAGE_STRING='nzbget 10.2'
|
||||
PACKAGE_BUGREPORT='hugbug@users.sourceforge.net'
|
||||
|
||||
ac_unique_file="nzbget.cpp"
|
||||
@@ -1235,7 +1235,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures nzbget 11.0-testing to adapt to many kinds of systems.
|
||||
\`configure' configures nzbget 10.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1306,7 +1306,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of nzbget 11.0-testing:";;
|
||||
short | recursive ) echo "Configuration of nzbget 10.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1315,7 +1315,6 @@ Optional Features:
|
||||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||
--disable-dependency-tracking speeds up one-time build
|
||||
--enable-dependency-tracking do not reject slow dependency extractors
|
||||
--disable-largefile omit support for large files
|
||||
--disable-curses do not use curses (removes dependency from
|
||||
curses-library)
|
||||
--disable-parcheck do not include par-check/-repair-support (removes
|
||||
@@ -1328,8 +1327,8 @@ Optional Features:
|
||||
--disable-gzip disable gzip-compression/decompression (removes
|
||||
dependency from zlib-library)
|
||||
--disable-sigchld-handler
|
||||
do not use sigchld-handler (the disabling may be
|
||||
neccessary on 32-Bit BSD)
|
||||
do not use sigchld-handler (the disabling is
|
||||
recommended for BSD)
|
||||
--enable-debug enable debugging
|
||||
|
||||
Optional Packages:
|
||||
@@ -1453,7 +1452,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
nzbget configure 11.0-testing
|
||||
nzbget configure 10.2
|
||||
generated by GNU Autoconf 2.61
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@@ -1467,7 +1466,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by nzbget $as_me 11.0-testing, which was
|
||||
It was created by nzbget $as_me 10.2, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2263,7 +2262,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=nzbget
|
||||
VERSION=11.0-testing
|
||||
VERSION=10.2
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@@ -3830,7 +3829,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
else
|
||||
ac_cv_header_stdc=no
|
||||
fi
|
||||
rm -f -r conftest*
|
||||
rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
@@ -3851,7 +3850,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
else
|
||||
ac_cv_header_stdc=no
|
||||
fi
|
||||
rm -f -r conftest*
|
||||
rm -f conftest*
|
||||
|
||||
fi
|
||||
|
||||
@@ -4722,149 +4721,64 @@ fi
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-largefile was given.
|
||||
if test "${enable_largefile+set}" = set; then
|
||||
enableval=$enable_largefile;
|
||||
fi
|
||||
|
||||
if test "$enable_largefile" != no; then
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
|
||||
echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_sys_largefile_CC+set}" = set; then
|
||||
{ echo "$as_me:$LINENO: checking for stat64" >&5
|
||||
echo $ECHO_N "checking for stat64... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_func_stat64+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_cv_sys_largefile_CC=no
|
||||
if test "$GCC" != yes; then
|
||||
ac_save_CC=$CC
|
||||
while :; do
|
||||
# IRIX 6.2 and later do not support large files by default,
|
||||
# so use the C compiler's -n32 option if that helps.
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <sys/types.h>
|
||||
/* Check that off_t can represent 2**63 - 1 correctly.
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
break
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext
|
||||
CC="$CC -n32"
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_sys_largefile_CC=' -n32'; break
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext
|
||||
break
|
||||
done
|
||||
CC=$ac_save_CC
|
||||
rm -f conftest.$ac_ext
|
||||
fi
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
|
||||
echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
|
||||
if test "$ac_cv_sys_largefile_CC" != no; then
|
||||
CC=$CC$ac_cv_sys_largefile_CC
|
||||
fi
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
|
||||
echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_sys_file_offset_bits+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
while :; do
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <sys/types.h>
|
||||
/* Check that off_t can represent 2**63 - 1 correctly.
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
/* Define stat64 to an innocuous variant, in case <limits.h> declares stat64.
|
||||
For example, HP-UX 11i <limits.h> declares gettimeofday. */
|
||||
#define stat64 innocuous_stat64
|
||||
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char stat64 (); below.
|
||||
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
|
||||
<limits.h> exists even on freestanding compilers. */
|
||||
|
||||
#ifdef __STDC__
|
||||
# include <limits.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#endif
|
||||
|
||||
#undef stat64
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char stat64 ();
|
||||
/* The GNU C library defines this for functions which it implements
|
||||
to always fail with ENOSYS. Some functions are actually named
|
||||
something starting with __ and the normal name is an alias. */
|
||||
#if defined __stub_stat64 || defined __stub___stat64
|
||||
choke me
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
return stat64 ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
@@ -4873,203 +4787,27 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_sys_file_offset_bits=no; break
|
||||
} && test -s conftest$ac_exeext &&
|
||||
$as_test_x conftest$ac_exeext; then
|
||||
ac_cv_func_stat64=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
ac_cv_func_stat64=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <sys/types.h>
|
||||
/* Check that off_t can represent 2**63 - 1 correctly.
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_sys_file_offset_bits=64; break
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_func_stat64" >&5
|
||||
echo "${ECHO_T}$ac_cv_func_stat64" >&6; }
|
||||
if test $ac_cv_func_stat64 = yes; then
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
ac_cv_sys_file_offset_bits=unknown
|
||||
break
|
||||
done
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
|
||||
echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
|
||||
case $ac_cv_sys_file_offset_bits in #(
|
||||
no | unknown) ;;
|
||||
*)
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_STAT64 1
|
||||
_ACEOF
|
||||
;;
|
||||
esac
|
||||
rm -f -r conftest*
|
||||
if test $ac_cv_sys_file_offset_bits = unknown; then
|
||||
{ echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
|
||||
echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_sys_large_files+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
while :; do
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <sys/types.h>
|
||||
/* Check that off_t can represent 2**63 - 1 correctly.
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_sys_large_files=no; break
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#define _LARGE_FILES 1
|
||||
#include <sys/types.h>
|
||||
/* Check that off_t can represent 2**63 - 1 correctly.
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_cv_sys_large_files=1; break
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
ac_cv_sys_large_files=unknown
|
||||
break
|
||||
done
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
|
||||
echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
|
||||
case $ac_cv_sys_large_files in #(
|
||||
no | unknown) ;;
|
||||
*)
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define _LARGE_FILES $ac_cv_sys_large_files
|
||||
_ACEOF
|
||||
;;
|
||||
esac
|
||||
rm -f -r conftest*
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -8828,9 +8566,17 @@ echo $ECHO_N "checking whether to use an empty SIGCHLD handler... $ECHO_C" >&6;
|
||||
if test "${enable_sigchld_handler+set}" = set; then
|
||||
enableval=$enable_sigchld_handler; SIGCHLDHANDLER=$enableval
|
||||
else
|
||||
SIGCHLDHANDLER=yes
|
||||
SIGCHLDHANDLER=auto
|
||||
fi
|
||||
|
||||
if test "$SIGCHLDHANDLER" = "auto"; then
|
||||
SIGCHLDHANDLER=yes
|
||||
case "$target" in
|
||||
*bsd*)
|
||||
SIGCHLDHANDLER=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $SIGCHLDHANDLER" >&5
|
||||
echo "${ECHO_T}$SIGCHLDHANDLER" >&6; }
|
||||
if test "$SIGCHLDHANDLER" = "yes"; then
|
||||
@@ -9537,7 +9283,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by nzbget $as_me 11.0-testing, which was
|
||||
This file was extended by nzbget $as_me 10.2, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -9590,7 +9336,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
nzbget config.status 11.0-testing
|
||||
nzbget config.status 10.2
|
||||
configured by $0, generated by GNU Autoconf 2.61,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
@@ -10272,7 +10018,7 @@ do
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
# First, check the format of the line:
|
||||
cat >"\$tmp/defines.sed" <<\\CEOF
|
||||
/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*/b def
|
||||
/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
|
||||
/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
|
||||
b
|
||||
:def
|
||||
|
||||
25
configure.ac
25
configure.ac
@@ -2,9 +2,9 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
AC_INIT(nzbget, 11.0-testing, hugbug@users.sourceforge.net)
|
||||
AC_INIT(nzbget, 10.2, hugbug@users.sourceforge.net)
|
||||
AC_CANONICAL_SYSTEM
|
||||
AM_INIT_AUTOMAKE(nzbget, 11.0-testing)
|
||||
AM_INIT_AUTOMAKE(nzbget, 10.2)
|
||||
AC_CONFIG_SRCDIR([nzbget.cpp])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
@@ -56,9 +56,10 @@ AC_CHECK_FUNC(getopt_long,
|
||||
|
||||
|
||||
dnl
|
||||
dnl use 64-Bits for file sizes
|
||||
dnl stat64
|
||||
dnl
|
||||
AC_SYS_LARGEFILE
|
||||
AC_CHECK_FUNC(stat64,
|
||||
[AC_DEFINE([HAVE_STAT64], 1, [Define to 1 if stat64 is supported])],)
|
||||
|
||||
|
||||
dnl
|
||||
@@ -502,14 +503,22 @@ fi
|
||||
dnl
|
||||
dnl Some Linux systems require an empty signal handler for SIGCHLD
|
||||
dnl in order for exit codes to be correctly delivered to parent process.
|
||||
dnl Some 32-Bit BSD systems however may not function properly if the handler is installed.
|
||||
dnl The default behavior is to install the handler.
|
||||
dnl Some BSD systems however may not function properly if the handler is installed.
|
||||
dnl The default behavior is to check the target and disable the handler on BSD but keep it enabled on other systems.
|
||||
dnl
|
||||
AC_MSG_CHECKING(whether to use an empty SIGCHLD handler)
|
||||
AC_ARG_ENABLE(sigchld-handler,
|
||||
[AS_HELP_STRING([--disable-sigchld-handler], [do not use sigchld-handler (the disabling may be neccessary on 32-Bit BSD)])],
|
||||
[AS_HELP_STRING([--disable-sigchld-handler], [do not use sigchld-handler (the disabling is recommended for BSD)])],
|
||||
[SIGCHLDHANDLER=$enableval],
|
||||
[SIGCHLDHANDLER=yes])
|
||||
[SIGCHLDHANDLER=auto])
|
||||
if test "$SIGCHLDHANDLER" = "auto"; then
|
||||
SIGCHLDHANDLER=yes
|
||||
case "$target" in
|
||||
*bsd*)
|
||||
SIGCHLDHANDLER=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($SIGCHLDHANDLER)
|
||||
if test "$SIGCHLDHANDLER" = "yes"; then
|
||||
AC_DEFINE([SIGCHLD_HANDLER], 1, [Define to 1 to install an empty signal handler for SIGCHLD])
|
||||
|
||||
50
nzbget-postprocess.conf
Normal file
50
nzbget-postprocess.conf
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# This file if part of nzbget
|
||||
#
|
||||
# Template configuration file for post-processing script "nzbget-postprocess.sh".
|
||||
# Please refer to "nzbget-postprocess.sh" for usage instructions.
|
||||
#
|
||||
# Copyright (C) 2008-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
##############################################################################
|
||||
### OPTIONS ###
|
||||
|
||||
# Rename img-files to iso (yes, no).
|
||||
RenameIMG=yes
|
||||
|
||||
# Joint TS-files (yes, no).
|
||||
JoinTS=yes
|
||||
|
||||
##############################################################################
|
||||
### POSTPROCESSING-PARAMETERS ###
|
||||
|
||||
# This section defines parameters, which can be set for each nzb-file
|
||||
# individually using either web-interface or command line.
|
||||
# Example command line for setting parameter "PostProcess" to value "no" for
|
||||
# nzb-file with id=2:
|
||||
# nzbget -E G O PostProcess=no 2
|
||||
|
||||
# Perform postprocessing (yes, no).
|
||||
#
|
||||
# Set to "no" to skip postprocessing for this nzb-file.
|
||||
PostProcess=yes
|
||||
|
||||
# Destination directory.
|
||||
DestDir=
|
||||
231
nzbget-postprocess.sh
Executable file
231
nzbget-postprocess.sh
Executable file
@@ -0,0 +1,231 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This file if part of nzbget
|
||||
#
|
||||
# Example postprocessing script for NZBGet
|
||||
#
|
||||
# Copyright (C) 2008 Peter Roubos <peterroubos@hotmail.com>
|
||||
# Copyright (C) 2008 Otmar Werner
|
||||
# Copyright (C) 2008-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
####################### Usage instructions #######################
|
||||
# o Script will cleanup, join ts-files and rename img-files to iso.
|
||||
#
|
||||
# o To use this script with nzbget set the option "PostProcess" in
|
||||
# nzbget configuration file to point to this script file. E.g.:
|
||||
# PostProcess=/home/user/nzbget/nzbget-postprocess.sh
|
||||
#
|
||||
# o The script needs a configuration file. An example configuration file
|
||||
# is provided in file "nzbget-postprocess.conf". Put the configuration file
|
||||
# into the directory where nzbget's configuration file (nzbget.conf) is located.
|
||||
# Then edit the configuration file in any text editor to adjust the settings.
|
||||
#
|
||||
# o You can also edit the script's configuration via web-interface.
|
||||
#
|
||||
# o There are few options, which can be ajdusted for each nzb-file individually.
|
||||
#
|
||||
####################### End of Usage instructions #######################
|
||||
|
||||
|
||||
# NZBGet passes following arguments to postprocess-programm as environment
|
||||
# variables:
|
||||
# NZBPP_DIRECTORY - path to destination dir for downloaded files;
|
||||
# NZBPP_NZBNAME - user-friendly name of processed nzb-file as it is displayed
|
||||
# by the program. The file path and extension are removed.
|
||||
# If download was renamed, this parameter reflects the new name;
|
||||
# NZBPP_NZBFILENAME - name of processed nzb-file. It includes file extension and also
|
||||
# may include full path;
|
||||
# NZBPP_CATEGORY - category assigned to nzb-file (can be empty string);
|
||||
# NZBPP_PARSTATUS - result of par-check:
|
||||
# 0 = not checked: par-check is disabled or nzb-file does
|
||||
# not contain any par-files;
|
||||
# 1 = checked and failed to repair;
|
||||
# 2 = checked and successfully repaired;
|
||||
# 3 = checked and can be repaired but repair is disabled.
|
||||
# NZBPP_UNPACKSTATUS - result of unpack:
|
||||
# 0 = unpack is disabled or was skipped due to nzb-file
|
||||
# properties or due to errors during par-check;
|
||||
# 1 = unpack failed;
|
||||
# 2 = unpack successful.
|
||||
|
||||
|
||||
# Name of script's configuration file
|
||||
SCRIPT_CONFIG_FILE="nzbget-postprocess.conf"
|
||||
|
||||
# Exit codes
|
||||
POSTPROCESS_PARCHECK_CURRENT=91
|
||||
POSTPROCESS_PARCHECK_ALL=92
|
||||
POSTPROCESS_SUCCESS=93
|
||||
POSTPROCESS_ERROR=94
|
||||
POSTPROCESS_NONE=95
|
||||
|
||||
# Check if the script is called from nzbget 10.0 or later
|
||||
if [ "$NZBPP_DIRECTORY" = "" -o "$NZBOP_CONFIGFILE" = "" ]; then
|
||||
echo "*** NZBGet post-processing script ***"
|
||||
echo "This script is supposed to be called from nzbget (10.0 or later)."
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
if [ "$NZBOP_UNPACK" = "" ]; then
|
||||
echo "[ERROR] This script requires nzbget version at least 10.0-testing-r555 or 10.0-stable."
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# Check if postprocessing was disabled in postprocessing parameters
|
||||
# (for current nzb-file) via web-interface or via command line with
|
||||
# "nzbget -E G O PostProcess=no <ID>"
|
||||
if [ "$NZBPR_PostProcess" = "no" ]; then
|
||||
echo "[WARNING] Post-Process: Post-processing disabled for this nzb-file, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
|
||||
echo "[INFO] Post-Process: Post-processing script successfully started"
|
||||
cd "$NZBPP_DIRECTORY"
|
||||
|
||||
# Determine the location of configuration file (it must be stored in
|
||||
# the directory with nzbget.conf).
|
||||
ConfigDir="${NZBOP_CONFIGFILE%/*}"
|
||||
ScriptConfigFile="$ConfigDir/$SCRIPT_CONFIG_FILE"
|
||||
if [ ! -f "$ScriptConfigFile" ]; then
|
||||
echo "[ERROR] Post-Process: Configuration file $ScriptConfigFile not found, exiting"
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# Readg configuration file
|
||||
while read line; do eval "$line"; done < $ScriptConfigFile
|
||||
|
||||
# Check nzbget.conf options
|
||||
BadConfig=0
|
||||
|
||||
if [ "$NZBOP_ALLOWREPROCESS" = "yes" ]; then
|
||||
echo "[ERROR] Post-Process: Please disable option \"AllowReProcess\" in nzbget configuration file"
|
||||
BadConfig=1
|
||||
fi
|
||||
|
||||
if [ "$NZBOP_UNPACK" != "yes" ]; then
|
||||
echo "[ERROR] Post-Process: Please enable option \"Unpack\" in nzbget configuration file"
|
||||
BadConfig=1
|
||||
fi
|
||||
|
||||
if [ "$BadConfig" -eq 1 ]; then
|
||||
echo "[ERROR] Post-Process: Exiting due to incompatible nzbget configuration"
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# Check par status
|
||||
if [ "$NZBPP_PARSTATUS" -eq 3 ]; then
|
||||
echo "[WARNING] Post-Process: Par-check successful, but Par-repair disabled, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
if [ "$NZBPP_PARSTATUS" -eq 1 ]; then
|
||||
echo "[WARNING] Post-Process: Par-check failed, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
|
||||
# Check unpack status
|
||||
if [ "$NZBPP_UNPACKSTATUS" -eq 1 ]; then
|
||||
echo "[WARNING] Post-Process: Unpack failed, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
if [ "$NZBPP_UNPACKSTATUS" -eq 0 -a "$NZBPP_PARSTATUS" -ne 2 ]; then
|
||||
# Unpack is disabled or was skipped due to nzb-file properties or due to errors during par-check
|
||||
|
||||
if (ls *.rar *.7z *.7z.??? >/dev/null 2>&1); then
|
||||
echo "[WARNING] Post-Process: Archive files exist but unpack skipped, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
|
||||
if (ls *.par2 >/dev/null 2>&1); then
|
||||
echo "[WARNING] Post-Process: Unpack skipped and par-check skipped (although par2-files exist), exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
|
||||
if [ -f "_brokenlog.txt" ]; then
|
||||
echo "[WARNING] Post-Process: _brokenlog.txt exists, download is probably damaged, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
|
||||
echo "[INFO] Post-Process: Neither archive- nor par2-files found, _brokenlog.txt doesn't exist, considering download successful"
|
||||
fi
|
||||
|
||||
# Check if destination directory exists (important for reprocessing of history items)
|
||||
if [ ! -d "$NZBPP_DIRECTORY" ]; then
|
||||
echo "[ERROR] Post-Process: Nothing to post-process: destination directory $NZBPP_DIRECTORY doesn't exist"
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# All checks done, now processing the files
|
||||
|
||||
# If download contains only nzb-files move them into nzb-directory
|
||||
# for further download
|
||||
# Check if command "wc" exists
|
||||
wc -l . >/dev/null 2>&1
|
||||
if [ "$?" -ne 127 ]; then
|
||||
AllFilesCount=`ls -1 2>/dev/null | wc -l`
|
||||
NZBFilesCount=`ls -1 *.nzb 2>/dev/null | wc -l`
|
||||
if [ "$AllFilesCount" -eq "$NZBFilesCount" ]; then
|
||||
echo "[INFO] Moving downloaded nzb-files into incoming nzb-directory for further download"
|
||||
mv *.nzb $NZBOP_NZBDIR
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
echo "[INFO] Post-Process: Cleaning up"
|
||||
chmod -R a+rw .
|
||||
rm *.nzb >/dev/null 2>&1
|
||||
rm *.sfv >/dev/null 2>&1
|
||||
rm *.1 >/dev/null 2>&1
|
||||
rm _brokenlog.txt >/dev/null 2>&1
|
||||
rm *.[pP][aA][rR]2 >/dev/null 2>&1
|
||||
|
||||
if [ "$JoinTS" = "yes" ]; then
|
||||
# Join any split .ts files if they are named xxxx.0000.ts xxxx.0001.ts
|
||||
# They will be joined together to a file called xxxx.0001.ts
|
||||
if (ls *.ts >/dev/null 2>&1); then
|
||||
echo "[INFO] Post-Process: Joining ts-files"
|
||||
tsname=`find . -name "*0001.ts" |awk -F/ '{print $NF}'`
|
||||
cat *0???.ts > ./$tsname
|
||||
|
||||
# Remove all the split .ts files
|
||||
echo "[INFO] Post-Process: Deleting source ts-files"
|
||||
rm *0???.ts >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$RenameIMG" = "yes" ]; then
|
||||
# Rename img file to iso
|
||||
# It will be renamed to .img.iso so you can see that it has been renamed
|
||||
if (ls *.img >/dev/null 2>&1); then
|
||||
echo "[INFO] Post-Process: Renaming img-files to iso"
|
||||
imgname=`find . -name "*.img" |awk -F/ '{print $NF}'`
|
||||
mv $imgname $imgname.iso
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if destination directory was set in postprocessing parameters
|
||||
# (for current nzb-file) via web-interface or via command line with
|
||||
# "nzbget -E G O DestDir=/new/path <ID>"
|
||||
if [ "$NZBPR_DestDir" != "" ]; then
|
||||
mkdir $NZBPR_DestDir
|
||||
mv * $NZBPR_DestDir >/dev/null 2>&1
|
||||
cd ..
|
||||
rmdir $NZBPP_DIRECTORY
|
||||
fi
|
||||
|
||||
# All OK, requesting cleaning up of download queue
|
||||
exit $POSTPROCESS_SUCCESS
|
||||
753
nzbget.conf
753
nzbget.conf
@@ -61,21 +61,6 @@ QueueDir=${MainDir}/queue
|
||||
# Directory to store temporary files.
|
||||
TempDir=${MainDir}/tmp
|
||||
|
||||
# Directory with web-interface files.
|
||||
#
|
||||
# Example: /usr/local/share/nzbget/webui.
|
||||
#
|
||||
# NOTE: To disable web-interface set the option to an empty value.
|
||||
# This however doesn't disable the built-in web-server completely because
|
||||
# it is also used to serve JSON-/XML-RPC requests.
|
||||
WebDir=
|
||||
|
||||
# Directory with post-processing scripts.
|
||||
#
|
||||
# NOTE: For information on writing post-processing scripts visit
|
||||
# http://nzbget.sourceforge.net/Post-processing_scripts.
|
||||
ScriptDir=${MainDir}/ppscripts
|
||||
|
||||
# Lock-file for daemon-mode, POSIX only.
|
||||
#
|
||||
# If the option is not empty, NZBGet creates the file and writes process-id
|
||||
@@ -87,19 +72,14 @@ LockFile=${MainDir}/nzbget.lock
|
||||
# NOTE: See also option <CreateLog>.
|
||||
LogFile=${DestDir}/nzbget.log
|
||||
|
||||
# Configuration file template.
|
||||
# Directory with web-interface files.
|
||||
#
|
||||
# Put the path to the example configuration file which comes with
|
||||
# NZBGet. Web-interface needs this file to read option descriptions.
|
||||
# Example: "WebDir=/usr/local/share/nzbget/webui".
|
||||
#
|
||||
# Do not put here your actual configuration file (typically stored
|
||||
# in your home directory or in /etc/nzbget.conf) but instead the unchanged
|
||||
# example configuration file (typically installed to
|
||||
# /usr/local/share/nzbget/nzbget.conf).
|
||||
#
|
||||
# Example: /usr/local/share/nzbget/nzbget.conf.
|
||||
ConfigTemplate=
|
||||
|
||||
# NOTE: To disable web-interface set the option to an empty value.
|
||||
# This however doesn't disable the built-in web-server completely because
|
||||
# it is also used to serve JSON-/XML-RPC requests.
|
||||
WebDir=
|
||||
|
||||
##############################################################################
|
||||
### NEWS-SERVERS ###
|
||||
@@ -175,7 +155,7 @@ Server1.Encryption=no
|
||||
# select cipher for TLS" if the cipher string is not valid.
|
||||
Server1.Cipher=
|
||||
|
||||
# Maximum number of simultaneous connections to this server (0-999).
|
||||
# Maximal number of simultaneous connections to this server (0-999).
|
||||
Server1.Connections=4
|
||||
|
||||
# Second server, on level 0.
|
||||
@@ -224,20 +204,10 @@ ControlIP=0.0.0.0
|
||||
# communication see option <SecurePort>.
|
||||
ControlPort=6789
|
||||
|
||||
# User name which NZBGet server and remote client use.
|
||||
#
|
||||
# Set to empty value to disable user name check (check only password).
|
||||
#
|
||||
# NOTE: this option was added in NZBGet 11. Older versions used predefined
|
||||
# not changeable user name "nzbget". Third-party tools or web-sites written
|
||||
# for older NZBGet versions may not have an option to define user name. In
|
||||
# this case you should set option <ControlUsername> to the default value
|
||||
# "nzbget" or use empty value.
|
||||
ControlUsername=nzbget
|
||||
|
||||
# Password which NZBGet server and remote client use.
|
||||
#
|
||||
# Set to empty value to disable authorization request.
|
||||
# For authorization to web-interface use predefined username "nzbget" (not configurable)
|
||||
# and the password defined here.
|
||||
ControlPassword=tegbzn6789
|
||||
|
||||
# Secure control of NZBGet server (yes, no).
|
||||
@@ -271,7 +241,7 @@ SecureKey=
|
||||
# NOTE: This option has effect only if the program was started from
|
||||
# root-account, otherwise it is ignored and the daemon runs under
|
||||
# current user id.
|
||||
DaemonUsername=root
|
||||
DaemonUserName=root
|
||||
|
||||
# Specify default umask (affects file permissions) for newly created
|
||||
# files, POSIX only (000-1000).
|
||||
@@ -289,6 +259,9 @@ UMask=1000
|
||||
# Create subdirectory with category-name in destination-directory (yes, no).
|
||||
AppendCategoryDir=yes
|
||||
|
||||
# Create subdirectory with nzb-filename in destination-directory (yes, no).
|
||||
AppendNzbDir=yes
|
||||
|
||||
# How often incoming-directory (option <NzbDir>) must be checked for new
|
||||
# nzb-files (seconds).
|
||||
#
|
||||
@@ -314,18 +287,14 @@ NzbDirFileAge=60
|
||||
# save the second file under the same filename as the first one.
|
||||
MergeNzb=no
|
||||
|
||||
# Set path to program, that must be executed before a nzb-file is added
|
||||
# to queue.
|
||||
# Set path to program, that must be executed before any file in incoming
|
||||
# directory (option <NzbDir>) is processed.
|
||||
#
|
||||
# This program is called each time a new file is found in incoming
|
||||
# directory (option <NzbDir>) or a file is received via RPC (web-interface,
|
||||
# command "nzbget --append", etc.).
|
||||
#
|
||||
# Example: ~/nzbprocess.sh.
|
||||
# Example: "NzbProcess=~/nzbprocess.sh".
|
||||
#
|
||||
# That program can unpack archives which were put in incoming directory, make
|
||||
# filename cleanup, change nzb-name, category, priority and post-processing
|
||||
# parameters of the nzb-file or do other things.
|
||||
# filename cleanup, assign category and post-processing parameters to nzb-file
|
||||
# or do something else.
|
||||
#
|
||||
# INFO FOR DEVELOPERS:
|
||||
# NZBGet passes following arguments to nzbprocess-program as environment
|
||||
@@ -333,13 +302,6 @@ MergeNzb=no
|
||||
# NZBNP_DIRECTORY - path to directory, where file is located. It is a directory
|
||||
# specified by the option <NzbDir> or a subdirectory;
|
||||
# NZBNP_FILENAME - name of file to be processed;
|
||||
# NZBNP_NZBNAME - nzb-name (without path but with extension);
|
||||
# NZBNP_CATEGORY - category of nzb-file;
|
||||
# NZBNP_PRIORITY - priority of nzb-file;
|
||||
# NZBNP_TOP - flag indicating that the file will be added to the top
|
||||
# of queue: 0 or 1;
|
||||
# NZBNP_PAUSED - flag indicating that the file will be added as
|
||||
# paused: 0 or 1.
|
||||
#
|
||||
# In addition to these arguments NZBGet passes all
|
||||
# nzbget.conf-options to nzbprocess-program as environment variables. These
|
||||
@@ -349,18 +311,14 @@ MergeNzb=no
|
||||
# "SERVER1_HOST". For options with predefined possible values (yes/no, etc.)
|
||||
# the values are passed always in lower case.
|
||||
#
|
||||
# The nzbprocess-script can change nzb-name, category, priority,
|
||||
# post-processing parameters and top-/paused-flags of the nzb-file
|
||||
# by printing special messages into standard output (which is processed
|
||||
# by NZBGet).
|
||||
# The nzbprocess-script can assign category, priority and post-processing
|
||||
# parameters to the current nzb-file by printing special messages into
|
||||
# standard output (which is processed by NZBGet).
|
||||
#
|
||||
# To change nzb-name use following syntax:
|
||||
# echo "[NZB] NZBNAME=my download";
|
||||
#
|
||||
# To change category:
|
||||
# To assign category use following syntax:
|
||||
# echo "[NZB] CATEGORY=my category";
|
||||
#
|
||||
# To change priority:
|
||||
# To assign priority:
|
||||
# echo "[NZB] PRIORITY=signed_integer_value";
|
||||
#
|
||||
# for example: to set priority higher than normal:
|
||||
@@ -369,14 +327,6 @@ MergeNzb=no
|
||||
# another example: use a negative value for "lower than normal" priority:
|
||||
# echo "[NZB] PRIORITY=-100";
|
||||
#
|
||||
# Although priority can be any integer value, the web-interface operates
|
||||
# with five predefined priorities:
|
||||
# -100 - very low priority;
|
||||
# -50 - low priority;
|
||||
# 0 - normal priority (default);
|
||||
# 50 - high priority;
|
||||
# 100 - very high priority.
|
||||
#
|
||||
# To assign post-processing parameters:
|
||||
# echo "[NZB] NZBPR_myvar=my value";
|
||||
#
|
||||
@@ -384,12 +334,6 @@ MergeNzb=no
|
||||
# parameter with name "myvar" and value "my value" will be associated
|
||||
# with nzb-file.
|
||||
#
|
||||
# To change top-flag (nzb-file will be added to the top of queue):
|
||||
# echo "[NZB] TOP=1";
|
||||
#
|
||||
# To change paused-flag (nzb-file will be added in paused state):
|
||||
# echo "[NZB] PAUSED=1";
|
||||
#
|
||||
# The nzbprocess-script can delete processed file, rename it or move somewhere.
|
||||
# After the calling of the script the file will be either added to queue
|
||||
# (if it was an nzb-file) or renamed by adding the extension ".processed".
|
||||
@@ -401,17 +345,16 @@ MergeNzb=no
|
||||
# NzbProcess-script before adding to queue. This feature allows
|
||||
# NzbProcess-script to prevent the scanning of nzb-files extracted from
|
||||
# archives, if they were already processed by the script.
|
||||
#
|
||||
# NOTE: Files added via RPC calls in particular from web-interface are
|
||||
# saved into incoming nzb-directory and then processed by the script.
|
||||
NzbProcess=
|
||||
|
||||
# Set path to program, that must be executed after a nzb-file is added
|
||||
# to queue.
|
||||
#
|
||||
# This program is called each time a new nzb-file is added to queue.
|
||||
# This program is called each time a new nzb-file is added to queue: from
|
||||
# nzb incoming directory, via command line call "nzbget -A filename.nzb",
|
||||
# via RPC-method "append" or from web-interface.
|
||||
#
|
||||
# Example: ~/nzbaddedprocess.sh.
|
||||
# Example: "NzbAddedProcess=~/nzbaddedprocess.sh".
|
||||
#
|
||||
# That program can modify the files in download queue (for example
|
||||
# delete or pause all nfo, sfv, sample files) or do something else.
|
||||
@@ -440,23 +383,25 @@ NzbProcess=
|
||||
#
|
||||
# Examples:
|
||||
# 1) pausing nzb-file using file-id:
|
||||
# "$NZBOP_APPBIN" -c "$NZBOP_CONFIGFILE" -E G P $NZBNA_LASTID;
|
||||
# "$NZBOP_APPBIN" -c "$NZBOP_CONFIGFILE" -E G P $NZBNA_LASTID
|
||||
#
|
||||
# 2) setting category using nzb-name:
|
||||
# "$NZBOP_APPBIN" -c "$NZBOP_CONFIGFILE" -E GN K "my cat" "$NZBNA_NZBNAME";
|
||||
# "$NZBOP_APPBIN" -c "$NZBOP_CONFIGFILE" -E GN K "my cat" "$NZBNA_NZBNAME"
|
||||
#
|
||||
# 3) pausing files with extension "nzb":
|
||||
# "$NZBOP_APPBIN" -c "$NZBOP_CONFIGFILE" -E FR P "$NZBNA_NZBNAME/.*\.nzb";
|
||||
# "$NZBOP_APPBIN" -c "$NZBOP_CONFIGFILE" -E FR P "$NZBNA_NAME/.*\.nzb"
|
||||
NzbAddedProcess=
|
||||
|
||||
# Check for duplicate files (yes, no).
|
||||
#
|
||||
# If this option is enabled the program checks by adding of a new nzb-file:
|
||||
# 1) if nzb-file contains duplicate entries. This check aims on detecting
|
||||
# of reposted files (if first file was not fully uploaded).
|
||||
# of reposted files (if first file was not fully uploaded);
|
||||
# If the program find two files with identical names, only the
|
||||
# biggest of these files will be added to queue;
|
||||
# 2) if download queue already contains file with the same name;
|
||||
# 3) if destination file on disk already exists.
|
||||
# In last two cases: if the file exists it will not be added to queue.
|
||||
# In last two cases: if the file exists it will not be added to queue;
|
||||
#
|
||||
# If this option is disabled, all files are downloaded and duplicate files
|
||||
# are renamed to "filename_duplicate1".
|
||||
@@ -493,11 +438,17 @@ ReloadPostQueue=yes
|
||||
# the file was completed.
|
||||
ContinuePartial=yes
|
||||
|
||||
# Visibly rename broken files on download appending "_broken" (yes, no).
|
||||
#
|
||||
# Do not activate this option if par-check is enabled.
|
||||
RenameBroken=no
|
||||
|
||||
# Decode articles (yes, no).
|
||||
#
|
||||
# yes - decode articles using internal decoder (supports yEnc and UU formats);
|
||||
# no - the articles will not be decoded and joined. Useful for debugging to
|
||||
# look at article's source text.
|
||||
# no - the articles will not be decoded and joined. External programs
|
||||
# (like "uudeview") can be used to decode and join downloaded articles.
|
||||
# Also useful for debugging to look at article's source text.
|
||||
Decode=yes
|
||||
|
||||
# Write decoded articles directly into destination output file (yes, no).
|
||||
@@ -580,6 +531,29 @@ ConnectionTimeout=60
|
||||
# Do not use small values!
|
||||
TerminateTimeout=600
|
||||
|
||||
# Set the (approximate) maximum number of allowed threads (10-999).
|
||||
#
|
||||
# Sometimes under certain circumstances the program may create way to many
|
||||
# download threads. Most of them are in wait-state. That is not bad,
|
||||
# but threads are usually a limited resource. If a program creates to many
|
||||
# of them, operating system may kill it. The option <ThreadLimit> prevents that.
|
||||
#
|
||||
# NOTE: The number of threads is not the same as the number of connections
|
||||
# opened to NNTP-servers. Do not use the option <ThreadLimit> to limit the
|
||||
# number of connections. Use the appropriate options <ServerX.Connections>
|
||||
# instead.
|
||||
#
|
||||
# NOTE: The actual number of created threads can be slightly larger as
|
||||
# defined by the option. Important threads may be created even if the
|
||||
# number of threads is exceeded. The option prevents only the creation of
|
||||
# additional download threads.
|
||||
#
|
||||
# NOTE: In most cases you should leave the default value "100" unchanged.
|
||||
# However you may increase that value if you need more than 90 connections
|
||||
# (that's very unlikely) or decrease the value if the OS does not allow so
|
||||
# many threads. But the most OSes should not have problems with 100 threads.
|
||||
ThreadLimit=100
|
||||
|
||||
# Set the maximum download rate on program start (kilobytes/sec).
|
||||
#
|
||||
# Value "0" means no speed control.
|
||||
@@ -658,7 +632,7 @@ DeleteCleanupDisk=no
|
||||
# that can be achieved with the option <ParCleanupQueue>.
|
||||
KeepHistory=7
|
||||
|
||||
# Maximum number of simultaneous connections for nzb URL downloads (0-999).
|
||||
# Maximal number of simultaneous connections for nzb URL downloads (0-999).
|
||||
#
|
||||
# When NZB-files are added to queue via URL, the program downloads them
|
||||
# from the specified URL. The option limits the maximal number of connections
|
||||
@@ -686,11 +660,6 @@ Category1.Name=Movies
|
||||
# destination directory.
|
||||
Category1.DestDir=
|
||||
|
||||
# Default list of post-processing scripts.
|
||||
#
|
||||
# For more information see global option <DefScript>.
|
||||
Category1.DefScript=
|
||||
|
||||
Category2.Name=Series
|
||||
Category3.Name=Music
|
||||
Category4.Name=Software
|
||||
@@ -723,6 +692,22 @@ DetailTarget=both
|
||||
# debug-mode: "./configure --enable-debug".
|
||||
DebugTarget=both
|
||||
|
||||
# Set the default message-kind for output received from process-scripts
|
||||
# (PostProcess, NzbProcess, TaskX.Process) (detail, info, warning,
|
||||
# error, debug, none).
|
||||
#
|
||||
# NZBGet checks if the line written by the script to stdout or stderr starts
|
||||
# with special character-sequence, determining the message-kind, e.g.:
|
||||
# [INFO] bla-bla.
|
||||
# [DETAIL] bla-bla.
|
||||
# [WARNING] bla-bla.
|
||||
# [ERROR] bla-bla.
|
||||
# [DEBUG] bla-bla.
|
||||
#
|
||||
# If the message-kind was detected the text is added to log with detected type.
|
||||
# Otherwise the message becomes the default kind, specified in this option.
|
||||
ProcessLogKind=detail
|
||||
|
||||
# Number of messages stored in buffer and available for remote
|
||||
# clients (messages).
|
||||
LogBufferSize=1000
|
||||
@@ -782,6 +767,306 @@ CursesTime=no
|
||||
UpdateInterval=200
|
||||
|
||||
|
||||
##############################################################################
|
||||
### PAR CHECK/REPAIR ###
|
||||
|
||||
# How many par2-files to load (one, all, none).
|
||||
#
|
||||
# one - only one main par2-file must be downloaded and other must be paused;
|
||||
# all - all par2-files must be downloaded;
|
||||
# none - all par2-files must be automatically paused.
|
||||
# Paused files remain in queue and can be unpaused by parchecker when needed.
|
||||
LoadPars=one
|
||||
|
||||
# Force par-verification (yes, no).
|
||||
#
|
||||
# Force par-check for every download. When set to "no" the par-check is
|
||||
# performed only if the unpacker or the post-processing script detect a
|
||||
# damaged download.
|
||||
#
|
||||
# To download only needed par2-files (smart par-files loading) set also
|
||||
# the option <LoadPars> to "one". If option <LoadPars> is set to "all",
|
||||
# all par2-files will be downloaded before verification and repair starts.
|
||||
# The option <RenameBroken> must be set to "no", otherwise the par-checker
|
||||
# may not find renamed files and fail.
|
||||
ParCheck=no
|
||||
|
||||
# Automatic par-repair (yes, no).
|
||||
#
|
||||
# If option <ParCheck> is enabled and <ParRepair> is not, the program
|
||||
# only verifies downloaded files and downloads needed par2-files, but does
|
||||
# not start repair-process. This is useful if computer does not have
|
||||
# enough CPU power, since repairing of large files may take too much
|
||||
# resources and time on a slow computers.
|
||||
ParRepair=yes
|
||||
|
||||
# What files should be scanned during par-verification (limited,
|
||||
# full, auto).
|
||||
#
|
||||
# limited - scan only files belonging to the par-set;
|
||||
# full - scan all files in the directory. This helps if the
|
||||
# files were renamed after creating of par-set.
|
||||
# auto - a limited scan is performed first. If the par-checker
|
||||
# detects missing files, it scans other files in the
|
||||
# directory until all required files are found.
|
||||
#
|
||||
# NOTE: for par-check/repair NZBGet uses library libpar2. The last and
|
||||
# widely used version 0.2 of the library has few bugs, sometimes causing
|
||||
# a crash of the program. This is especially true when using "full" or
|
||||
# "auto" par-scan. NZBGet is supplied with patches addressing these
|
||||
# issues. Please apply the patches to libpar2 and recompile it.
|
||||
ParScan=auto
|
||||
|
||||
# Use only par2-files with matching names (yes, no).
|
||||
#
|
||||
# If par-check needs extra par-blocks it searches for par2-files
|
||||
# in download queue, which can be unpaused and used for restore.
|
||||
# These par2-files should have the same base name as the main par2-file,
|
||||
# currently loaded in par-checker. Sometimes extra par files (especially if
|
||||
# they were uploaded by a different poster) have not matching names.
|
||||
# Normally par-checker does not use these files, but you can allow it
|
||||
# to use these files by setting <StrictParName> to "no".
|
||||
# This has however a side effect: if NZB-file contains more than one collection
|
||||
# of files (with different par-sets), par-checker may download par-files from
|
||||
# a wrong collection. This increases you traffic (but not harm par-check).
|
||||
#
|
||||
# NOTE: Par-checker always uses only par-files added from the same NZB-file
|
||||
# and the option <StrictParName> does not change this behavior.
|
||||
StrictParName=yes
|
||||
|
||||
# Maximum allowed time for par-repair (minutes).
|
||||
#
|
||||
# Value "0" means unlimited.
|
||||
#
|
||||
# If you use NZBGet on a very slow computer like NAS-device, it may be good to
|
||||
# limit the time allowed for par-repair. NZBGet calculates the estimated time
|
||||
# required for par-repair. If the estimated value exceeds the limit defined
|
||||
# here, NZBGet cancels the repair.
|
||||
#
|
||||
# To avoid a false cancellation NZBGet compares the estimated time with
|
||||
# <ParTimeLimit> after the first 5 minutes of repairing, when the calculated
|
||||
# estimated time is more or less accurate. But in a case if <ParTimeLimit> is
|
||||
# set to a value smaller than 5 minutes, the comparison is made after the first
|
||||
# whole minute.
|
||||
#
|
||||
# NOTE: The option limits only the time required for repairing. It doesn't
|
||||
# affect the first stage of parcheck - verification of files. However the
|
||||
# verification speed is constant, it doesn't depend on files integrity and
|
||||
# therefore it is not necessary to limit the time needed for the first stage.
|
||||
#
|
||||
# NOTE: This option requires an extended version of libpar2 (the original
|
||||
# version doesn't support the cancelling of repairing). Please refer to
|
||||
# NZBGet's README for info on how to apply the patch to libpar2.
|
||||
ParTimeLimit=0
|
||||
|
||||
# Pause download queue during check/repair (yes, no).
|
||||
#
|
||||
# Enable the option to give CPU more time for par-check/repair. That helps
|
||||
# to speed up check/repair on slow CPUs with fast connection (e.g. NAS-devices).
|
||||
#
|
||||
# NOTE: If parchecker needs additional par-files it temporarily unpauses
|
||||
# the queue.
|
||||
#
|
||||
# NOTE: See also options <PostPauseQueue> and <UnpackPauseQueue>.
|
||||
ParPauseQueue=no
|
||||
|
||||
# Cleanup download queue after successful check/repair (yes, no).
|
||||
#
|
||||
# Enable this option for automatic deletion of unneeded (paused) par-files
|
||||
# from download queue after successful check/repair.
|
||||
ParCleanupQueue=yes
|
||||
|
||||
# Delete source nzb-file after successful check/repair (yes, no).
|
||||
#
|
||||
# Enable this option for automatic deletion of nzb-file from incoming directory
|
||||
# after successful check/repair.
|
||||
NzbCleanupDisk=no
|
||||
|
||||
|
||||
##############################################################################
|
||||
### UNPACK ###
|
||||
|
||||
# Unpack downloaded nzb-files (yes, no).
|
||||
#
|
||||
# If the download is damaged and could not be repaired using par-files
|
||||
# the unpacking is not performed.
|
||||
#
|
||||
# If the option <ParCheck> is disabled the program will try to unpack
|
||||
# downloaded files first. If the unpacking fails the par-check/repair
|
||||
# is performed and the unpack will be executed again.
|
||||
Unpack=yes
|
||||
|
||||
# Pause download queue during unpack (yes, no).
|
||||
#
|
||||
# Enable the option to give CPU more time for unpacking. That helps
|
||||
# to speed up unpacking on slow CPUs.
|
||||
#
|
||||
# NOTE: See also options <ParPauseQueue> and <PostPauseQueue>.
|
||||
UnpackPauseQueue=no
|
||||
|
||||
# Delete archive files after successful unpacking (yes, no).
|
||||
UnpackCleanupDisk=yes
|
||||
|
||||
# Full path to unrar executable.
|
||||
#
|
||||
# Example: "/usr/bin/unrar".
|
||||
#
|
||||
# If unrar is in your PATH you may leave the path part and set only
|
||||
# the executable name ("unrar" on POSIX or "unrar.exe" on Windows).
|
||||
UnrarCmd=unrar
|
||||
|
||||
# Full path to 7-Zip executable.
|
||||
#
|
||||
# Example: "/usr/bin/7z".
|
||||
#
|
||||
# If 7-Zip binary is in your PATH you may leave the path part and set only
|
||||
# the executable name ("7z" or "7za" on POSIX or "7z.exe" on Windows).
|
||||
SevenZipCmd=7z
|
||||
|
||||
|
||||
##############################################################################
|
||||
### POST-PROCESSING ###
|
||||
|
||||
# Set path to program, that must be executed after the download of nzb-file
|
||||
# is completed and possibly par-checked/repaired and unpacked, depending
|
||||
# on other options.
|
||||
#
|
||||
# Example: "PostProcess=~/nzbget-postprocess.sh".
|
||||
#
|
||||
# NOTE: An example script is provided within distribution in file
|
||||
# "nzbget-postprocess.sh".
|
||||
#
|
||||
# NOTE: Since version 10.0 NZBGet has a built-in support for unpack
|
||||
# (option <Unpack>). In the previous versions unpack was performed by
|
||||
# post-processing scripts. If you use a script created for older NZBGet
|
||||
# version you need to disable the built-in unpack for script to operate
|
||||
# properly.
|
||||
#
|
||||
# INFO FOR DEVELOPERS:
|
||||
# If the option <AllowReProcess> is disabled (that's the default setting)
|
||||
# the post-processing script is executed once per nzb-file after
|
||||
# par-check/repair (if needed) and unpacking (if enabled).
|
||||
#
|
||||
# If the option <AllowReProcess> is active the post-processing script is
|
||||
# executed for each collection within nzb-file (for nzb-files having multiple
|
||||
# collections but at least once). Depending on option <ParCheck> the collection
|
||||
# could be already par-checked/repaired or the script could be called without
|
||||
# par-check taken place. In the latest case if the script detects errors
|
||||
# (such as unpack failed) it has an ability to request par-check from
|
||||
# NZBGet. After par-check/repair NZBGet calls the script once again.
|
||||
#
|
||||
# NZBGet passes following arguments to post-processing script as environment
|
||||
# variables:
|
||||
# NZBPP_DIRECTORY - path to destination dir for downloaded files;
|
||||
# NZBPP_NZBNAME - user-friendly name of processed nzb-file as it is displayed
|
||||
# by the program. The file path and extension are removed.
|
||||
# If download was renamed, this parameter reflects the new name;
|
||||
# NZBPP_NZBFILENAME - name of processed nzb-file. It includes file extension and also
|
||||
# may include full path;
|
||||
# NZBPP_CATEGORY - category assigned to nzb-file (can be empty string);
|
||||
# NZBPP_PARSTATUS - result of par-check:
|
||||
# 0 = not checked: par-check is disabled or nzb-file does
|
||||
# not contain any par-files;
|
||||
# 1 = checked and failed to repair;
|
||||
# 2 = checked and successfully repaired;
|
||||
# 3 = checked and can be repaired but repair is disabled.
|
||||
# NZBPP_UNPACKSTATUS - result of unpack:
|
||||
# 0 = unpack is disabled or was skipped due to nzb-file
|
||||
# properties or due to errors during par-check;
|
||||
# 1 = unpack failed;
|
||||
# 2 = unpack successful.
|
||||
#
|
||||
# In addition the following arguments are passed if the option <AllowReProcess>
|
||||
# is active:
|
||||
# NZBPP_PARFILENAME - name of par-file or empty string (if no collections were
|
||||
# found);
|
||||
# NZBPP_PARFAILED - indication of failed par-jobs for current nzb-file:
|
||||
# 0 = no failed par-jobs;
|
||||
# 1 = current par-job or any of the previous par-jobs for
|
||||
# the same nzb-files failed;
|
||||
# NZBPP_NZBCOMPLETED - state of nzb-job:
|
||||
# 0 = there are more collections in this nzb-file queued;
|
||||
# 1 = this was the last collection in nzb-file.
|
||||
#
|
||||
# If nzb-file has associated postprocess-parameters (which can be set using
|
||||
# subcommand <O> of command <-E>, for example: NZBGet -E G O "myvar=hello !" 10)
|
||||
# or using XML-/JSON-RPC (for example via web-interface), they are also passed
|
||||
# as environment variables. These variables have prefix "NZBPR_" in their names.
|
||||
# For example, pp-parameter "myvar" will be passed as environment
|
||||
# variable "NZBPR_myvar".
|
||||
#
|
||||
# In addition to arguments and postprocess-parameters NZBGet passes all
|
||||
# nzbget.conf-options to postprocess-program as environment variables. These
|
||||
# variables have prefix "NZBOP_" and are written in UPPER CASE. For Example
|
||||
# option "ParRepair" is passed as environment variable "NZBOP_PARREPAIR".
|
||||
# The dots in option names are replaced with underscores, for example
|
||||
# "SERVER1_HOST". For options with predefined possible values (yes/no, etc.)
|
||||
# the values are passed always in lower case.
|
||||
#
|
||||
# Return value: NZBGet processes the exit code returned by the script:
|
||||
# 93 - post-process successful (status = SUCCESS);
|
||||
# 94 - post-process failed (status = FAILURE);
|
||||
# 95 - post-process skipped (status = NONE);
|
||||
# 91 - request NZBGet to do par-check/repair for current collection in the
|
||||
# current nzb-file. This return code is accepted only if the
|
||||
# option <AllowReProcess> is active;
|
||||
# 92 - request NZBGet to do par-check/repair for all collections (par-sets)
|
||||
# in the current nzb-file.
|
||||
# All other return codes are interpreted as "status unknown".
|
||||
#
|
||||
# The return value is used to display the status of post-processing in
|
||||
# a history view. In addition to status one or more text messages can be
|
||||
# passed to history using a special prefix "[HISTORY]" by printing messages
|
||||
# to standard output. For example:
|
||||
# echo "[ERROR] [HISTORY] Unpack failed, not enough disk space";
|
||||
#
|
||||
# NOTE: If the option <AllowReProcess> is active NZBGet calls the script
|
||||
# for each collection within nzb-file. The term "collection" actually means
|
||||
# "par-set". To determine what "collections" are present in nzb-file NZBGet
|
||||
# looks for par-sets. If any collection of files within nzb-file does
|
||||
# not have any par-files, this collection will not be detected.
|
||||
# For example, for nzb-file containing three collections but only two par-sets,
|
||||
# the postprocess will be called two times - after processing of each par-set.
|
||||
# If NZBGet doesn't find any collections it calls PostProcess once
|
||||
# with empty string for parameter NZBPP_PARFILENAME.
|
||||
PostProcess=
|
||||
|
||||
# Allow multiple post-processing for the same nzb-file (yes, no).
|
||||
#
|
||||
# NOTE: Enable this option only if you were advised to do that by the author
|
||||
# of the post-processing script.
|
||||
#
|
||||
# NOTE: By enabling <AllowReProcess> you should disable the option <ParCheck>
|
||||
# to prevent multiple par-checking.
|
||||
#
|
||||
# INFO FOR DEVELOPERS:
|
||||
# This option affects the post-processing in several ways:
|
||||
# 1) If the option is active the post-processing script (option <PostProcess>)
|
||||
# is called for each collection (par-set) within nzb-file;
|
||||
# 2) The post-processing script may be called multiple times when nzb-file
|
||||
# reaches the state "completely downloaded". This can be needed if
|
||||
# the par-check/-repair is performed by the post-processing script
|
||||
# (instead of relying on NZBGet's built-in par-check-feature).
|
||||
#
|
||||
# NOTE: If the built-in unpacking is active (option <Unpack>) this option
|
||||
# is ignored (as if it were set to "no").
|
||||
#
|
||||
# NOTE: If you develop a script depending on this option you should check
|
||||
# if the option is active when your script is started and generate an
|
||||
# error message if the option is not set correctly. You should also check
|
||||
# the option <Unpack> because if it's active the option <AllowReProcess>
|
||||
# doesn't work too.
|
||||
AllowReProcess=no
|
||||
|
||||
# Pause download queue during executing of postprocess-script (yes, no).
|
||||
#
|
||||
# Enable the option to give CPU more time for postprocess-script. That helps
|
||||
# to speed up postprocess on slow CPUs with fast connection (e.g. NAS-devices).
|
||||
#
|
||||
# NOTE: See also options <ParPauseQueue> and <UnpackPauseQueue>.
|
||||
PostPauseQueue=no
|
||||
|
||||
|
||||
##############################################################################
|
||||
### SCHEDULER ###
|
||||
|
||||
@@ -830,7 +1115,7 @@ UpdateInterval=200
|
||||
|
||||
# Path to the program to execute if the command is "Process".
|
||||
#
|
||||
# Example: /home/user/fetch-nzb.sh.
|
||||
# Example: "Task1.Process=/home/user/fetch-nzb.sh".
|
||||
#
|
||||
# If the option <TaskX.Command> is not set to "Process" this option
|
||||
# is ignored and can be omitted.
|
||||
@@ -849,275 +1134,3 @@ UpdateInterval=200
|
||||
#Task2.WeekDays=1-7
|
||||
#Task2.Command=DownloadRate
|
||||
#Task2.DownloadRate=0
|
||||
|
||||
|
||||
##############################################################################
|
||||
### PAR CHECK/REPAIR ###
|
||||
|
||||
# Whether and how par-verification must be performed (auto, force, manual).
|
||||
#
|
||||
# Auto - par-check is performed when needed. One par2-file is always
|
||||
# downloaded. Additional par2-files are downloaded if needed
|
||||
# for repair. Repair is performed if the option <ParRepair>
|
||||
# is enabled;
|
||||
# Force - force par-check for every download (even undamaged). All
|
||||
# par2-files are always downloaded. Repair is performed if
|
||||
# the option <ParRepair> is enabled;
|
||||
# Manual - par-check is skipped. One par2-file is always
|
||||
# downloaded. If a damaged download is detected, all
|
||||
# par2-files are downloaded but neithet par-check nor par-repair
|
||||
# take place. The download can be then repaired manually
|
||||
# (possibly on another, faster computer).
|
||||
ParCheck=auto
|
||||
|
||||
# Automatic par-repair after par-verification (yes, no).
|
||||
#
|
||||
# If option <ParCheck> is set to "Auto" or "Force" this option defines
|
||||
# if the download must be repaired when needed. The option can be
|
||||
# disabled if computer does not have enough CPU power, since repairing
|
||||
# may take too much resources and time on a slow computers.
|
||||
ParRepair=yes
|
||||
|
||||
# What files should be scanned during par-verification (limited,
|
||||
# full, auto).
|
||||
#
|
||||
# Limited - scan only files belonging to the par-set;
|
||||
# Full - scan all files in the directory. This helps if the
|
||||
# files were renamed after creating of par-set;
|
||||
# Auto - a limited scan is performed first. If the par-checker
|
||||
# detects missing files, it scans other files in the
|
||||
# directory until all required files are found.
|
||||
#
|
||||
# NOTE: for par-check/repair NZBGet uses library libpar2. The last and
|
||||
# widely used version 0.2 of the library has few bugs, sometimes causing
|
||||
# a crash of the program. This is especially true when using "full" or
|
||||
# "auto" par-scan. NZBGet is supplied with patches addressing these
|
||||
# issues. Please apply the patches to libpar2 and recompile it.
|
||||
ParScan=auto
|
||||
|
||||
# Use only par2-files with matching names (yes, no).
|
||||
#
|
||||
# If par-check needs extra par-blocks it looks for paused par2-files
|
||||
# in the download queue. These par2-files should have the same base name
|
||||
# as the main par2-file, currently loaded in par-checker. Sometimes extra
|
||||
# par2-files have non-matching names (especially if they were uploaded
|
||||
# by a different poster). Normally par-checker does not use these files, but
|
||||
# you can allow it to use them by setting <StrictParName> to "no".
|
||||
# There is a small side effect then: if NZB-file contains more than one
|
||||
# collection of files (with different par-sets), par-checker may download
|
||||
# par2-files from a wrong collection and will need to unpause other
|
||||
# par2-files until all required files are downloaded. This increases the
|
||||
# traffic (but not harm the par-check).
|
||||
#
|
||||
# NOTE: Par-checker always uses only par-files added from the same NZB-file
|
||||
# and the option <StrictParName> does not change this behavior.
|
||||
StrictParName=yes
|
||||
|
||||
# Maximum allowed time for par-repair (minutes).
|
||||
#
|
||||
# Value "0" means unlimited.
|
||||
#
|
||||
# If you use NZBGet on a very slow computer like NAS-device, it may be good to
|
||||
# limit the time allowed for par-repair. NZBGet calculates the estimated time
|
||||
# required for par-repair. If the estimated value exceeds the limit defined
|
||||
# here, NZBGet cancels the repair.
|
||||
#
|
||||
# To avoid a false cancellation NZBGet compares the estimated time with
|
||||
# <ParTimeLimit> after the first 5 minutes of repairing, when the calculated
|
||||
# estimated time is more or less accurate. But in a case if <ParTimeLimit> is
|
||||
# set to a value smaller than 5 minutes, the comparison is made after the first
|
||||
# whole minute.
|
||||
#
|
||||
# NOTE: The option limits only the time required for repairing. It doesn't
|
||||
# affect the first stage of parcheck - verification of files. However the
|
||||
# verification speed is constant, it doesn't depend on files integrity and
|
||||
# therefore it is not necessary to limit the time needed for the first stage.
|
||||
#
|
||||
# NOTE: This option requires an extended version of libpar2 (the original
|
||||
# version doesn't support the cancelling of repairing). Please refer to
|
||||
# NZBGet's README for info on how to apply the patch to libpar2.
|
||||
ParTimeLimit=0
|
||||
|
||||
# Pause download queue during check/repair (yes, no).
|
||||
#
|
||||
# Enable the option to give CPU more time for par-check/repair. That helps
|
||||
# to speed up check/repair on slow CPUs with fast connection (e.g. NAS-devices).
|
||||
#
|
||||
# NOTE: If parchecker needs additional par-files it temporarily unpauses
|
||||
# the queue.
|
||||
#
|
||||
# NOTE: See also options <ScriptPauseQueue> and <UnpackPauseQueue>.
|
||||
ParPauseQueue=no
|
||||
|
||||
# Cleanup download queue after successful check/repair (yes, no).
|
||||
#
|
||||
# Enable this option for automatic deletion of unneeded (paused) par-files
|
||||
# from download queue after successful check/repair.
|
||||
ParCleanupQueue=yes
|
||||
|
||||
# Delete source nzb-file after successful check/repair (yes, no).
|
||||
#
|
||||
# Enable this option for automatic deletion of nzb-file from incoming directory
|
||||
# after successful check/repair.
|
||||
NzbCleanupDisk=no
|
||||
|
||||
# Files to delete after successful check/repair.
|
||||
#
|
||||
# List of file extensions or file names to delete after successful
|
||||
# check/repair. The entries must be separated with commas. The entries
|
||||
# can be file extensions or any text the file name may end with.
|
||||
#
|
||||
# Example: .par2, .sfv
|
||||
ExtCleanupDisk=.par2, .sfv, _brokenlog.txt
|
||||
|
||||
|
||||
##############################################################################
|
||||
### UNPACK ###
|
||||
|
||||
# Unpack downloaded nzb-files (yes, no).
|
||||
#
|
||||
# If the download is damaged and could not be repaired using par-files
|
||||
# the unpacking is not performed.
|
||||
#
|
||||
# If the option <ParCheck> is disabled the program will try to unpack
|
||||
# downloaded files first. If the unpacking fails the par-check/repair
|
||||
# is performed and the unpack will be executed again.
|
||||
Unpack=yes
|
||||
|
||||
# Pause download queue during unpack (yes, no).
|
||||
#
|
||||
# Enable the option to give CPU more time for unpacking. That helps
|
||||
# to speed up unpacking on slow CPUs.
|
||||
#
|
||||
# NOTE: See also options <ParPauseQueue> and <ScriptPauseQueue>.
|
||||
UnpackPauseQueue=no
|
||||
|
||||
# Delete archive files after successful unpacking (yes, no).
|
||||
UnpackCleanupDisk=yes
|
||||
|
||||
# Full path to unrar executable.
|
||||
#
|
||||
# Example: /usr/bin/unrar.
|
||||
#
|
||||
# If unrar is in your PATH you may leave the path part and set only
|
||||
# the executable name ("unrar" on POSIX or "unrar.exe" on Windows).
|
||||
UnrarCmd=unrar
|
||||
|
||||
# Full path to 7-Zip executable.
|
||||
#
|
||||
# Example: /usr/bin/7z.
|
||||
#
|
||||
# If 7-Zip binary is in your PATH you may leave the path part and set only
|
||||
# the executable name ("7z" or "7za" on POSIX or "7z.exe" on Windows).
|
||||
SevenZipCmd=7z
|
||||
|
||||
|
||||
##############################################################################
|
||||
### POST-PROCESSING SCRIPTS ###
|
||||
|
||||
# Default list of post-processing scripts to execute after the download
|
||||
# of nzb-file is completed and possibly par-checked/repaired and unpacked,
|
||||
# depending on other options.
|
||||
#
|
||||
# The scripts in the list must be separated with commas or semicolons. Only
|
||||
# filenames without path must be used. All scripts must be stored in directory
|
||||
# pointed by option <ScriptDir>.
|
||||
#
|
||||
# Example: Cleanup.sh, Move.sh, EMail.py.
|
||||
#
|
||||
# Each download (nzb-file) has its own list of post-processing scripts. The option
|
||||
# <DefScript> is the default value assigned to download when it is added to
|
||||
# queue. The list of post-processing scripts for a particular download can be
|
||||
# changed in the edit dialog in web-interface or using remote command "--edit/-E".
|
||||
#
|
||||
# When nzb-file is added to queue it can have a category assigned to it. In this
|
||||
# case the option <CategoryX.DefScript> (if not empty) overrides the
|
||||
# global option <DefScript>.
|
||||
#
|
||||
# NOTE: The script execution order is controlled by option <ScriptOrder>, not
|
||||
# by their order in option <DefScript>.
|
||||
#
|
||||
# NOTE: Changing options <DefScript> and <CategoryX.DefScript> doesn't affect
|
||||
# already queued downloads.
|
||||
#
|
||||
# NOTE: For the list of interesting post-processing scripts see
|
||||
# http://nzbget.sourceforge.net/Catalog_of_post-processing_scripts.
|
||||
#
|
||||
# INFO FOR DEVELOPERS:
|
||||
# NOTE: This is a short documentation, for more information visit
|
||||
# http://nzbget.sourceforge.net/Post-processing_scripts.
|
||||
#
|
||||
# NZBGet passes following arguments to post-processing script as environment
|
||||
# variables:
|
||||
# NZBPP_DIRECTORY - path to destination dir for downloaded files;
|
||||
# NZBPP_NZBNAME - user-friendly name of processed nzb-file as it is displayed
|
||||
# by the program. The file path and extension are removed.
|
||||
# If download was renamed, this parameter reflects the new name;
|
||||
# NZBPP_NZBFILENAME - name of processed nzb-file. It includes file extension and also
|
||||
# may include full path;
|
||||
# NZBPP_CATEGORY - category assigned to nzb-file (can be empty string);
|
||||
# NZBPP_PARSTATUS - result of par-check:
|
||||
# 0 = not checked: par-check is disabled or nzb-file does
|
||||
# not contain any par-files;
|
||||
# 1 = checked and failed to repair;
|
||||
# 2 = checked and successfully repaired;
|
||||
# 3 = checked and can be repaired but repair is disabled;
|
||||
# 4 = par-check needed but skipped (option ParCheck=manual);
|
||||
# NZBPP_UNPACKSTATUS - result of unpack:
|
||||
# 0 = unpack is disabled or was skipped due to nzb-file
|
||||
# properties or due to errors during par-check;
|
||||
# 1 = unpack failed;
|
||||
# 2 = unpack successful.
|
||||
#
|
||||
# If the script defines own options they are also passed as environment
|
||||
# variables. These variables have prefix "NZBPO_" in their names. For
|
||||
# example, option "myoption" will be passed as environment variable
|
||||
# "NZBPO_myoption" and in addition in uppercase as "NZBPO_MYOPTION".
|
||||
#
|
||||
# If the script defines own post-processing parameters, they are also passed as
|
||||
# environment variables. These variables have prefix "NZBPR_" in their
|
||||
# names. For example, pp-parameter "myparam" will be passed as environment
|
||||
# variable "NZBPR_myparam" and in addition in uppercase as "NZBPR_MYPARAM".
|
||||
#
|
||||
# In addition to arguments, pp-options and pp-parameters NZBGet passes all
|
||||
# nzbget.conf-options to pp-script as environment variables. These
|
||||
# variables have prefix "NZBOP_" and are written in UPPER CASE. For Example
|
||||
# option "ParRepair" is passed as environment variable "NZBOP_PARREPAIR". The
|
||||
# dots in option names are replaced with underscores, for example
|
||||
# "SERVER1_HOST". For options with predefined possible values (yes/no, etc.)
|
||||
# the values are passed always in lower case.
|
||||
#
|
||||
# Return value: NZBGet processes the exit code returned by the script:
|
||||
# 93 - post-process successful (status = SUCCESS);
|
||||
# 94 - post-process failed (status = FAILURE);
|
||||
# 95 - post-process skipped (status = NONE). Use this code when you script
|
||||
# terminates immediateley without doing any job and when this is not
|
||||
# a failure termination;
|
||||
# 92 - request NZBGet to do par-check/repair for current nzb-file.
|
||||
#
|
||||
# All other return codes are interpreted as failure (status = FAILURE).
|
||||
#
|
||||
# NOTE: This is a short documentation, for more information visit
|
||||
# http://nzbget.sourceforge.net/Post-processing_scripts.
|
||||
DefScript=
|
||||
|
||||
# Execution order for scripts.
|
||||
#
|
||||
# If you assign multiple scripts to one nzb-file, they are executed in the
|
||||
# order defined by this option. Scripts not listed here are executed at
|
||||
# the end in their alphabetical order.
|
||||
#
|
||||
# The scripts in the list must be separated with commas or semicolons. Only
|
||||
# filenames without path must be used. All scripts must be stored in directory
|
||||
# pointed by option <ScriptDir>.
|
||||
#
|
||||
# Example: Cleanup.sh, Move.sh.
|
||||
ScriptOrder=
|
||||
|
||||
# Pause download queue during executing of postprocess-script (yes, no).
|
||||
#
|
||||
# Enable the option to give CPU more time for postprocess-script. That helps
|
||||
# to speed up postprocess on slow CPUs with fast connection (e.g. NAS-devices).
|
||||
#
|
||||
# NOTE: See also options <ParPauseQueue> and <UnpackPauseQueue>.
|
||||
ScriptPauseQueue=no
|
||||
|
||||
25
nzbget.cpp
25
nzbget.cpp
@@ -2,7 +2,7 @@
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -74,7 +74,6 @@
|
||||
#include "PrePostProcessor.h"
|
||||
#include "ParChecker.h"
|
||||
#include "Scheduler.h"
|
||||
#include "Scanner.h"
|
||||
#include "Util.h"
|
||||
#ifdef WIN32
|
||||
#include "NTService.h"
|
||||
@@ -114,7 +113,6 @@ Log* g_pLog = NULL;
|
||||
PrePostProcessor* g_pPrePostProcessor = NULL;
|
||||
DiskState* g_pDiskState = NULL;
|
||||
Scheduler* g_pScheduler = NULL;
|
||||
Scanner* g_pScanner = NULL;
|
||||
int g_iArgumentCount;
|
||||
char* (*g_szEnvironmentVariables)[] = NULL;
|
||||
char* (*g_szArguments)[] = NULL;
|
||||
@@ -225,19 +223,16 @@ void Run(bool bReload)
|
||||
|
||||
g_pLog->InitOptions();
|
||||
|
||||
if (g_pOptions->GetDaemonMode())
|
||||
if (g_pOptions->GetDaemonMode() && !bReload)
|
||||
{
|
||||
#ifdef WIN32
|
||||
info("nzbget %s service-mode", Util::VersionRevision());
|
||||
#else
|
||||
if (!bReload)
|
||||
{
|
||||
Daemonize();
|
||||
}
|
||||
Daemonize();
|
||||
info("nzbget %s daemon-mode", Util::VersionRevision());
|
||||
#endif
|
||||
}
|
||||
else if (g_pOptions->GetServerMode())
|
||||
else if (g_pOptions->GetServerMode() && !bReload)
|
||||
{
|
||||
info("nzbget %s server-mode", Util::VersionRevision());
|
||||
}
|
||||
@@ -312,7 +307,6 @@ void Run(bool bReload)
|
||||
// Creating PrePostProcessor
|
||||
if (!g_pOptions->GetRemoteClientMode())
|
||||
{
|
||||
g_pScanner = new Scanner();
|
||||
g_pPrePostProcessor = new PrePostProcessor();
|
||||
}
|
||||
|
||||
@@ -347,7 +341,7 @@ void Run(bool bReload)
|
||||
// Standalone-mode
|
||||
if (!g_pOptions->GetServerMode())
|
||||
{
|
||||
NZBFile* pNZBFile = NZBFile::Create(g_pOptions->GetArgFilename(), g_pOptions->GetAddCategory() ? g_pOptions->GetAddCategory() : "");
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromFile(g_pOptions->GetArgFilename(), g_pOptions->GetAddCategory() ? g_pOptions->GetAddCategory() : "");
|
||||
if (!pNZBFile)
|
||||
{
|
||||
abort("FATAL ERROR: Parsing NZB-document %s failed\n\n", g_pOptions->GetArgFilename() ? g_pOptions->GetArgFilename() : "N/A");
|
||||
@@ -748,11 +742,6 @@ void Cleanup()
|
||||
delete g_pPrePostProcessor;
|
||||
g_pPrePostProcessor = NULL;
|
||||
}
|
||||
if (g_pScanner)
|
||||
{
|
||||
delete g_pScanner;
|
||||
g_pScanner = NULL;
|
||||
}
|
||||
debug("PrePostProcessor deleted");
|
||||
|
||||
debug("Deleting Frontend");
|
||||
@@ -844,14 +833,14 @@ void Daemonize()
|
||||
/* Drop user if there is one, and we were run as root */
|
||||
if ( getuid() == 0 || geteuid() == 0 )
|
||||
{
|
||||
struct passwd *pw = getpwnam(g_pOptions->GetDaemonUsername());
|
||||
struct passwd *pw = getpwnam(g_pOptions->GetDaemonUserName());
|
||||
if (pw)
|
||||
{
|
||||
fchown(lfp, pw->pw_uid, pw->pw_gid); /* change owner of lock file */
|
||||
setgroups( 0, (const gid_t*) 0 ); /* Set aux groups to null. */
|
||||
setgid(pw->pw_gid); /* Set primary group. */
|
||||
/* Try setting aux groups correctly - not critical if this fails. */
|
||||
initgroups( g_pOptions->GetDaemonUsername(),pw->pw_gid);
|
||||
initgroups( g_pOptions->GetDaemonUserName(),pw->pw_gid);
|
||||
/* Finally, set uid. */
|
||||
setuid(pw->pw_uid);
|
||||
}
|
||||
|
||||
4
nzbget.h
4
nzbget.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -37,8 +37,6 @@
|
||||
#define fdopen _fdopen
|
||||
#define ctime_r(timep, buf, bufsize) ctime_s(buf, bufsize, timep)
|
||||
#define localtime_r(time, tm) localtime_s(tm, time)
|
||||
#define strtok_r(str, delim, saveptr) strtok_s(str, delim, saveptr)
|
||||
#define strerror_r(errnum, buffer, size) strerror_s(buffer, size, errnum)
|
||||
#define int32_t __int32
|
||||
#define mkdir(dir, flags) _mkdir(dir)
|
||||
#define rmdir _rmdir
|
||||
|
||||
274
nzbget.kdevelop
Normal file
274
nzbget.kdevelop
Normal file
@@ -0,0 +1,274 @@
|
||||
<?xml version = '1.0'?>
|
||||
<kdevelop>
|
||||
<general>
|
||||
<author>gnu</author>
|
||||
<email/>
|
||||
<version>0.3.0</version>
|
||||
<projectmanagement>KDevAutoProject</projectmanagement>
|
||||
<primarylanguage>C++</primarylanguage>
|
||||
<keywords>
|
||||
<keyword>C++</keyword>
|
||||
<keyword>Code</keyword>
|
||||
</keywords>
|
||||
<ignoreparts>
|
||||
<part>kdevabbrev</part>
|
||||
<part>kdevbookmarks</part>
|
||||
<part>kdevsnippet</part>
|
||||
<part>kdevctags2</part>
|
||||
<part>kdevdoxygen</part>
|
||||
<part>kdevkonsoleview</part>
|
||||
<part>kdevfilegroups</part>
|
||||
<part>kdevfilelist</part>
|
||||
<part>kdevfileview</part>
|
||||
<part>kdevdistpart</part>
|
||||
<part>kdevopenwith</part>
|
||||
<part>kdevregexptest</part>
|
||||
<part>kdevscripting</part>
|
||||
<part>kdevfilter</part>
|
||||
<part>kdevtexttools</part>
|
||||
</ignoreparts>
|
||||
<projectdirectory>.</projectdirectory>
|
||||
<absoluteprojectpath>false</absoluteprojectpath>
|
||||
<description/>
|
||||
<projectname>nzbget</projectname>
|
||||
<defaultencoding/>
|
||||
<versioncontrol>kdevsubversion</versioncontrol>
|
||||
</general>
|
||||
<kdevautoproject>
|
||||
<general>
|
||||
<activetarget>src/nzbget</activetarget>
|
||||
<useconfiguration>default</useconfiguration>
|
||||
</general>
|
||||
<run>
|
||||
<mainprogram>/home/user/nzbget/nzbget</mainprogram>
|
||||
<terminal>false</terminal>
|
||||
<directoryradio>executable</directoryradio>
|
||||
<customdirectory>/</customdirectory>
|
||||
<programargs/>
|
||||
<autocompile>true</autocompile>
|
||||
<envvars/>
|
||||
<globaldebugarguments></globaldebugarguments>
|
||||
<globalcwd>/home/user/nzbget</globalcwd>
|
||||
<useglobalprogram>true</useglobalprogram>
|
||||
<autoinstall>false</autoinstall>
|
||||
<autokdesu>false</autokdesu>
|
||||
</run>
|
||||
<configurations>
|
||||
<default>
|
||||
<envvars/>
|
||||
<configargs>--enable-debug</configargs>
|
||||
<builddir/>
|
||||
<topsourcedir/>
|
||||
<cppflags/>
|
||||
<ldflags/>
|
||||
<ccompiler>kdevgccoptions</ccompiler>
|
||||
<cxxcompiler>kdevgppoptions</cxxcompiler>
|
||||
<f77compiler>kdevpgf77options</f77compiler>
|
||||
<ccompilerbinary/>
|
||||
<cxxcompilerbinary/>
|
||||
<f77compilerbinary/>
|
||||
<cflags/>
|
||||
<cxxflags/>
|
||||
<f77flags/>
|
||||
</default>
|
||||
</configurations>
|
||||
<make>
|
||||
<envvars>
|
||||
<envvar value="1" name="WANT_AUTOCONF_2_5" />
|
||||
<envvar value="1" name="WANT_AUTOMAKE_1_6" />
|
||||
</envvars>
|
||||
<abortonerror>true</abortonerror>
|
||||
<runmultiplejobs>false</runmultiplejobs>
|
||||
<numberofjobs>1</numberofjobs>
|
||||
<dontact>false</dontact>
|
||||
<makebin/>
|
||||
<prio>0</prio>
|
||||
</make>
|
||||
</kdevautoproject>
|
||||
<kdevdoctreeview>
|
||||
<ignoretocs>
|
||||
<toc>ada</toc>
|
||||
<toc>ada_bugs_gcc</toc>
|
||||
<toc>bash</toc>
|
||||
<toc>bash_bugs</toc>
|
||||
<toc>clanlib</toc>
|
||||
<toc>w3c-dom-level2-html</toc>
|
||||
<toc>fortran_bugs_gcc</toc>
|
||||
<toc>gnome1</toc>
|
||||
<toc>gnustep</toc>
|
||||
<toc>gtk</toc>
|
||||
<toc>gtk_bugs</toc>
|
||||
<toc>haskell</toc>
|
||||
<toc>haskell_bugs_ghc</toc>
|
||||
<toc>java_bugs_gcc</toc>
|
||||
<toc>java_bugs_sun</toc>
|
||||
<toc>kde2book</toc>
|
||||
<toc>opengl</toc>
|
||||
<toc>pascal_bugs_fp</toc>
|
||||
<toc>php</toc>
|
||||
<toc>php_bugs</toc>
|
||||
<toc>perl</toc>
|
||||
<toc>perl_bugs</toc>
|
||||
<toc>python</toc>
|
||||
<toc>python_bugs</toc>
|
||||
<toc>qt-kdev3</toc>
|
||||
<toc>ruby</toc>
|
||||
<toc>ruby_bugs</toc>
|
||||
<toc>sdl</toc>
|
||||
<toc>w3c-svg</toc>
|
||||
<toc>sw</toc>
|
||||
<toc>w3c-uaag10</toc>
|
||||
<toc>wxwidgets_bugs</toc>
|
||||
</ignoretocs>
|
||||
<ignoreqt_xml>
|
||||
<toc>Guide to the Qt Translation Tools</toc>
|
||||
<toc>Qt Assistant Manual</toc>
|
||||
<toc>Qt Designer Manual</toc>
|
||||
<toc>Qt Reference Documentation</toc>
|
||||
<toc>qmake User Guide</toc>
|
||||
</ignoreqt_xml>
|
||||
<ignoredoxygen>
|
||||
<toc>KDE Libraries (Doxygen)</toc>
|
||||
</ignoredoxygen>
|
||||
</kdevdoctreeview>
|
||||
<kdevfilecreate>
|
||||
<filetypes/>
|
||||
<useglobaltypes>
|
||||
<type ext="cpp" />
|
||||
<type ext="h" />
|
||||
</useglobaltypes>
|
||||
</kdevfilecreate>
|
||||
<kdevfileview>
|
||||
<groups>
|
||||
<group pattern="*.h" name="Header files" />
|
||||
<group pattern="*.cpp" name="Source files" />
|
||||
<hidenonprojectfiles>false</hidenonprojectfiles>
|
||||
<hidenonlocation>false</hidenonlocation>
|
||||
</groups>
|
||||
<tree>
|
||||
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
|
||||
<hidenonprojectfiles>false</hidenonprojectfiles>
|
||||
</tree>
|
||||
</kdevfileview>
|
||||
<kdevdocumentation>
|
||||
<projectdoc>
|
||||
<docsystem>Doxygen Documentation Collection</docsystem>
|
||||
<docurl>nzbget.tag</docurl>
|
||||
<usermanualurl/>
|
||||
</projectdoc>
|
||||
</kdevdocumentation>
|
||||
<substmap>
|
||||
<APPNAME>nzbget</APPNAME>
|
||||
<APPNAMELC>nzbget</APPNAMELC>
|
||||
<APPNAMESC>Nzbget</APPNAMESC>
|
||||
<APPNAMEUC>NZBGET</APPNAMEUC>
|
||||
<AUTHOR>gnu</AUTHOR>
|
||||
<EMAIL/>
|
||||
<LICENSE>GPL</LICENSE>
|
||||
<LICENSEFILE>COPYING</LICENSEFILE>
|
||||
<VERSION>0.3.0</VERSION>
|
||||
<YEAR>2007</YEAR>
|
||||
<dest>/home/user/nzbget-0.3.0/nzbget</dest>
|
||||
</substmap>
|
||||
<cppsupportpart>
|
||||
<filetemplates>
|
||||
<interfacesuffix>.h</interfacesuffix>
|
||||
<implementationsuffix>.cpp</implementationsuffix>
|
||||
</filetemplates>
|
||||
</cppsupportpart>
|
||||
<kdevcppsupport>
|
||||
<qt>
|
||||
<used>false</used>
|
||||
<version>3</version>
|
||||
<root></root>
|
||||
<includestyle>3</includestyle>
|
||||
<designerintegration>EmbeddedKDevDesigner</designerintegration>
|
||||
<qmake></qmake>
|
||||
<designer></designer>
|
||||
<designerpluginpaths/>
|
||||
</qt>
|
||||
<codecompletion>
|
||||
<includeGlobalFunctions>true</includeGlobalFunctions>
|
||||
<includeTypes>true</includeTypes>
|
||||
<includeEnums>true</includeEnums>
|
||||
<includeTypedefs>false</includeTypedefs>
|
||||
<automaticCodeCompletion>false</automaticCodeCompletion>
|
||||
<automaticArgumentsHint>false</automaticArgumentsHint>
|
||||
<automaticHeaderCompletion>true</automaticHeaderCompletion>
|
||||
<codeCompletionDelay>250</codeCompletionDelay>
|
||||
<argumentsHintDelay>400</argumentsHintDelay>
|
||||
<headerCompletionDelay>250</headerCompletionDelay>
|
||||
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
|
||||
<completionBoxItemOrder>0</completionBoxItemOrder>
|
||||
<howEvaluationContextMenu>true</howEvaluationContextMenu>
|
||||
<showCommentWithArgumentHint>false</showCommentWithArgumentHint>
|
||||
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
|
||||
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
|
||||
<processPrimaryTypes>true</processPrimaryTypes>
|
||||
<processFunctionArguments>false</processFunctionArguments>
|
||||
<preProcessAllHeaders>false</preProcessAllHeaders>
|
||||
<parseMissingHeaders>false</parseMissingHeaders>
|
||||
<resolveIncludePaths>true</resolveIncludePaths>
|
||||
<alwaysParseInBackground>true</alwaysParseInBackground>
|
||||
<usePermanentCaching>true</usePermanentCaching>
|
||||
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
|
||||
<includePaths>.;</includePaths>
|
||||
</codecompletion>
|
||||
<creategettersetter>
|
||||
<prefixGet/>
|
||||
<prefixSet>set</prefixSet>
|
||||
<prefixVariable>m_,_</prefixVariable>
|
||||
<parameterName>theValue</parameterName>
|
||||
<inlineGet>true</inlineGet>
|
||||
<inlineSet>true</inlineSet>
|
||||
</creategettersetter>
|
||||
<references/>
|
||||
<splitheadersource>
|
||||
<enabled>false</enabled>
|
||||
<synchronize>true</synchronize>
|
||||
<orientation>Vertical</orientation>
|
||||
</splitheadersource>
|
||||
</kdevcppsupport>
|
||||
<kdevdebugger>
|
||||
<general>
|
||||
<programargs>--standalone /home/user/.nzbget/nzb/t1.nzb</programargs>
|
||||
<gdbpath/>
|
||||
<dbgshell/>
|
||||
<configGdbScript/>
|
||||
<runShellScript/>
|
||||
<runGdbScript/>
|
||||
<breakonloadinglibs>true</breakonloadinglibs>
|
||||
<separatetty>true</separatetty>
|
||||
<floatingtoolbar>false</floatingtoolbar>
|
||||
</general>
|
||||
<display>
|
||||
<staticmembers>false</staticmembers>
|
||||
<demanglenames>true</demanglenames>
|
||||
<outputradix>10</outputradix>
|
||||
</display>
|
||||
</kdevdebugger>
|
||||
<dist>
|
||||
<custom>false</custom>
|
||||
<bzip>false</bzip>
|
||||
<archname/>
|
||||
<appname>nzbget</appname>
|
||||
<version>0.2.4</version>
|
||||
<release/>
|
||||
<vendor/>
|
||||
<licence/>
|
||||
<summary/>
|
||||
<group/>
|
||||
<packager/>
|
||||
<description/>
|
||||
<changelog/>
|
||||
<devpackage>false</devpackage>
|
||||
<docspackage>false</docspackage>
|
||||
<appicon>false</appicon>
|
||||
<arch>0</arch>
|
||||
<genHTML>false</genHTML>
|
||||
<useRPM>false</useRPM>
|
||||
<ftpkde>false</ftpkde>
|
||||
<appskde>false</appskde>
|
||||
<url/>
|
||||
</dist>
|
||||
</kdevelop>
|
||||
@@ -1,218 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# E-Mail post-processing script for NZBGet
|
||||
#
|
||||
# Copyright (C) 2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# $Revision$
|
||||
# $Date$
|
||||
#
|
||||
|
||||
|
||||
##############################################################################
|
||||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
|
||||
# Send E-Mail notification.
|
||||
#
|
||||
# This script sends E-Mail notification when the job is done.
|
||||
#
|
||||
# NOTE: This script requires Python to be installed on your system.
|
||||
|
||||
##############################################################################
|
||||
### OPTIONS ###
|
||||
|
||||
# Email address you want this email to be sent from.
|
||||
#From="NZBGet" <myaccount@gmail.com>
|
||||
|
||||
# Email address you want this email to be sent to.
|
||||
#To=myaccount@gmail.com
|
||||
|
||||
# SMTP server host.
|
||||
#Server=smtp.gmail.com
|
||||
|
||||
# SMTP server port (1-65535).
|
||||
#Port=25
|
||||
|
||||
# Secure communication using TLS/SSL (yes, no).
|
||||
#Encryption=yes
|
||||
|
||||
# SMTP server user name, if required.
|
||||
#Username=myaccount
|
||||
|
||||
# SMTP server password, if required.
|
||||
#Password=mypass
|
||||
|
||||
# Append list of files to the message (yes, no).
|
||||
#
|
||||
# Add the list of downloaded files (the content of destination directory).
|
||||
#FileList=yes
|
||||
|
||||
# Append broken-log to the message (yes, no).
|
||||
#
|
||||
# Add the content of file _brokenlog.txt. This file contains the list of damaged
|
||||
# files and the result of par-check/repair. For successful downloads the broken-log
|
||||
# is usually deleted by cleanup-script and therefore is not sent.
|
||||
#BrokenLog=yes
|
||||
|
||||
# Append post-processing log to the message (Always, Never, OnFailure).
|
||||
#
|
||||
# Add the post-processing log of active job.
|
||||
#PostProcessLog=OnFailure
|
||||
|
||||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
try:
|
||||
from xmlrpclib import ServerProxy # python 2
|
||||
except ImportError:
|
||||
from xmlrpc.client import ServerProxy # python 3
|
||||
|
||||
# Exit codes used by NZBGet
|
||||
POSTPROCESS_SUCCESS=93
|
||||
POSTPROCESS_ERROR=94
|
||||
|
||||
# Check if the script is called from nzbget 11.0 or later
|
||||
if not 'NZBOP_SCRIPTDIR' in os.environ:
|
||||
print('*** NZBGet post-processing script ***')
|
||||
print('This script is supposed to be called from nzbget (11.0 or later).')
|
||||
sys.exit(POSTPROCESS_ERROR)
|
||||
|
||||
print('[DETAIL] Script successfully started')
|
||||
sys.stdout.flush()
|
||||
|
||||
required_options = ('NZBPO_FROM', 'NZBPO_TO', 'NZBPO_SERVER', 'NZBPO_PORT', 'NZBPO_ENCRYPTION',
|
||||
'NZBPO_USERNAME', 'NZBPO_PASSWORD', 'NZBPO_FILELIST', 'NZBPO_BROKENLOG', 'NZBPO_POSTPROCESSLOG')
|
||||
for optname in required_options:
|
||||
if (not optname in os.environ):
|
||||
print('[ERROR] Option %s is missing in configuration file. Please check script settings' % optname[6:])
|
||||
sys.exit(POSTPROCESS_ERROR)
|
||||
|
||||
# Check par and unpack status for errors.
|
||||
success=False
|
||||
if os.environ['NZBPP_PARSTATUS'] == '1' or os.environ['NZBPP_UNPACKSTATUS'] == '1':
|
||||
subject = 'Failure for "%s"' % (os.environ['NZBPP_NZBNAME'])
|
||||
text = 'Download of "%s" has failed.' % (os.environ['NZBPP_NZBNAME'])
|
||||
elif os.environ['NZBPP_PARSTATUS'] == '4':
|
||||
subject = 'Damaged for "%s"' % (os.environ['NZBPP_NZBNAME'])
|
||||
text = 'Download of "%s" requires par-repair.' % (os.environ['NZBPP_NZBNAME'])
|
||||
else:
|
||||
subject = 'Success for "%s"' % (os.environ['NZBPP_NZBNAME'])
|
||||
text = 'Download of "%s" has successfully completed.' % (os.environ['NZBPP_NZBNAME'])
|
||||
success=True
|
||||
|
||||
# NZBPP_PARSTATUS - result of par-check:
|
||||
# 0 = not checked: par-check is disabled or nzb-file does
|
||||
# not contain any par-files;
|
||||
# 1 = checked and failed to repair;
|
||||
# 2 = checked and successfully repaired;
|
||||
# 3 = checked and can be repaired but repair is disabled.
|
||||
# 4 = par-check needed but skipped (option ParCheck=manual);
|
||||
parStatus = { '0': 'skipped', '1': 'failed', '2': 'repaired', '3': 'repairable', '4': 'manual' }
|
||||
text += '\nPar-Status: %s' % parStatus[os.environ['NZBPP_PARSTATUS']]
|
||||
|
||||
# NZBPP_UNPACKSTATUS - result of unpack:
|
||||
# 0 = unpack is disabled or was skipped due to nzb-file
|
||||
# properties or due to errors during par-check;
|
||||
# 1 = unpack failed;
|
||||
# 2 = unpack successful.
|
||||
unpackStatus = { '0': 'skipped', '1': 'failed', '2': 'success' }
|
||||
text += '\nUnpack-Status: %s' % unpackStatus[os.environ['NZBPP_UNPACKSTATUS']]
|
||||
|
||||
# add list of downloaded files
|
||||
if os.environ['NZBPO_FILELIST'] == 'yes':
|
||||
text += '\n\nFiles:'
|
||||
for dirname, dirnames, filenames in os.walk(os.environ['NZBPP_DIRECTORY']):
|
||||
for filename in filenames:
|
||||
text += '\n' + os.path.join(dirname, filename)[len(os.environ['NZBPP_DIRECTORY']) + 1:]
|
||||
|
||||
# add _brokenlog.txt (if exists)
|
||||
if os.environ['NZBPO_BROKENLOG'] == 'yes':
|
||||
brokenlog = '%s/_brokenlog.txt' % os.environ['NZBPP_DIRECTORY']
|
||||
if os.path.exists(brokenlog):
|
||||
text += '\n\nBrokenlog:\n' + open(brokenlog, 'r').read().strip()
|
||||
|
||||
# add post-processing log
|
||||
if os.environ['NZBPO_POSTPROCESSLOG'] == 'Always' or \
|
||||
(os.environ['NZBPO_POSTPROCESSLOG'] == 'OnFailure' and not success):
|
||||
# To get the post-processing log we connect to NZBGet via XML-RPC
|
||||
# and call method "postqueue", which returns the list of post-processing job.
|
||||
# The first item in the list is current job. This item has a field 'Log',
|
||||
# containing an array of log-entries.
|
||||
# For more info visit http://nzbget.sourceforge.net/RPC_API_reference
|
||||
|
||||
# First we need to know connection info: host, port and password of NZBGet server.
|
||||
# NZBGet passes all configuration options to post-processing script as
|
||||
# environment variables.
|
||||
host = os.environ['NZBOP_CONTROLIP'];
|
||||
port = os.environ['NZBOP_CONTROLPORT'];
|
||||
username = os.environ['NZBOP_CONTROLUSERNAME'];
|
||||
password = os.environ['NZBOP_CONTROLPASSWORD'];
|
||||
|
||||
if host == '0.0.0.0': host = '127.0.0.1'
|
||||
|
||||
# Build an URL for XML-RPC requests
|
||||
rpcUrl = 'http://%s:%s@%s:%s/xmlrpc' % (username, password, host, port);
|
||||
|
||||
# Create remote server object
|
||||
server = ServerProxy(rpcUrl)
|
||||
|
||||
# Call remote method 'postqueue'. The only parameter tells how many log-entries to return as maximum.
|
||||
postqueue = server.postqueue(10000)
|
||||
|
||||
# Get field 'Log' from the first post-processing job
|
||||
log = postqueue[0]['Log']
|
||||
|
||||
# Now iterate through entries and save them to message text
|
||||
if len(log) > 0:
|
||||
text += '\n\nPost-processing log:';
|
||||
for entry in log:
|
||||
text += '\n%s\t%s\t%s' % (entry['Kind'], datetime.datetime.fromtimestamp(int(entry['Time'])), entry['Text'])
|
||||
|
||||
# Create message
|
||||
msg = MIMEText(text)
|
||||
msg['Subject'] = subject
|
||||
msg['From'] = os.environ['NZBPO_FROM']
|
||||
msg['To'] = os.environ['NZBPO_TO']
|
||||
|
||||
# Send message
|
||||
print('[DETAIL] Sending E-Mail')
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
smtp = smtplib.SMTP(os.environ['NZBPO_SERVER'], os.environ['NZBPO_PORT'])
|
||||
|
||||
if os.environ['NZBPO_ENCRYPTION'] == 'yes':
|
||||
smtp.starttls()
|
||||
|
||||
if os.environ['NZBPO_USERNAME'] != '' and os.environ['NZBPO_PASSWORD'] != '':
|
||||
smtp.login(os.environ['NZBPO_USERNAME'], os.environ['NZBPO_PASSWORD'])
|
||||
|
||||
smtp.sendmail(os.environ['NZBPO_FROM'], os.environ['NZBPO_TO'], msg.as_string())
|
||||
|
||||
smtp.quit()
|
||||
except Exception as err:
|
||||
print('[ERROR] %s' % err)
|
||||
sys.exit(POSTPROCESS_ERROR)
|
||||
|
||||
# All OK, returning exit status 'POSTPROCESS_SUCCESS' (int <93>) to let NZBGet know
|
||||
# that our script has successfully completed.
|
||||
sys.exit(POSTPROCESS_SUCCESS)
|
||||
@@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Logger post-processing script for NZBGet
|
||||
#
|
||||
# Copyright (C) 2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# $Revision$
|
||||
# $Date$
|
||||
#
|
||||
|
||||
|
||||
##############################################################################
|
||||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
|
||||
# Save post-processing log into a file.
|
||||
#
|
||||
# This script saves post-processing log of nzb-file into file
|
||||
# _postprocesslog.txt in the destination directory.
|
||||
#
|
||||
# NOTE: This script requires Python to be installed on your system.
|
||||
|
||||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
try:
|
||||
from xmlrpclib import ServerProxy # python 2
|
||||
except ImportError:
|
||||
from xmlrpc.client import ServerProxy # python 3
|
||||
|
||||
# Exit codes used by NZBGet
|
||||
POSTPROCESS_SUCCESS=93
|
||||
POSTPROCESS_NONE=95
|
||||
POSTPROCESS_ERROR=94
|
||||
|
||||
# Check if the script is called from nzbget 11.0 or later
|
||||
if not 'NZBOP_SCRIPTDIR' in os.environ:
|
||||
print('*** NZBGet post-processing script ***')
|
||||
print('This script is supposed to be called from nzbget (11.0 or later).')
|
||||
sys.exit(POSTPROCESS_ERROR)
|
||||
|
||||
if not os.path.exists(os.environ['NZBPP_DIRECTORY']):
|
||||
print('Destination directory doesn\'t exist, exiting')
|
||||
sys.exit(POSTPROCESS_NONE)
|
||||
|
||||
# To get the post-processing log we connect to NZBGet via XML-RPC
|
||||
# and call method "postqueue", which returns the list of post-processing job.
|
||||
# The first item in the list is current job. This item has a field 'Log',
|
||||
# containing an array of log-entries.
|
||||
# For more info visit http://nzbget.sourceforge.net/RPC_API_reference
|
||||
|
||||
# First we need to know connection info: host, port and password of NZBGet server.
|
||||
# NZBGet passes all configuration options to post-processing script as
|
||||
# environment variables.
|
||||
host = os.environ['NZBOP_CONTROLIP'];
|
||||
port = os.environ['NZBOP_CONTROLPORT'];
|
||||
username = os.environ['NZBOP_CONTROLUSERNAME'];
|
||||
password = os.environ['NZBOP_CONTROLPASSWORD'];
|
||||
|
||||
if host == '0.0.0.0': host = '127.0.0.1'
|
||||
|
||||
# Build an URL for XML-RPC requests
|
||||
rpcUrl = 'http://%s:%s@%s:%s/xmlrpc' % (username, password, host, port);
|
||||
|
||||
# Create remote server object
|
||||
server = ServerProxy(rpcUrl)
|
||||
|
||||
# Call remote method 'postqueue'. The only parameter tells how many log-entries to return as maximum.
|
||||
postqueue = server.postqueue(10000)
|
||||
|
||||
# Get field 'Log' from the first post-processing job
|
||||
log = postqueue[0]['Log']
|
||||
|
||||
# Now iterate through entries and save them to the output file
|
||||
if len(log) > 0:
|
||||
f = open('%s/_postprocesslog.txt' % os.environ['NZBPP_DIRECTORY'], 'wb')
|
||||
for entry in log:
|
||||
f.write((u'%s\t%s\t%s\n' % (entry['Kind'], datetime.datetime.fromtimestamp(int(entry['Time'])), entry['Text'])).encode('utf8'))
|
||||
f.close()
|
||||
|
||||
# All OK, returning exit status 'POSTPROCESS_SUCCESS' (int <93>) to let NZBGet know
|
||||
# that our script has successfully completed.
|
||||
sys.exit(POSTPROCESS_SUCCESS)
|
||||
1288
webui/config.js
1288
webui/config.js
File diff suppressed because it is too large
Load Diff
@@ -416,14 +416,7 @@ var Downloads = (new function($)
|
||||
notification = '#Notif_Downloads_Resumed';
|
||||
RPC.call('editqueue', ['GroupResume', 0, '', checkedEditIDs], function()
|
||||
{
|
||||
if (Options.option('ParCheck') === 'force')
|
||||
{
|
||||
editCompleted();
|
||||
}
|
||||
else
|
||||
{
|
||||
RPC.call('editqueue', ['GroupPauseExtraPars', 0, '', checkedEditIDs], editCompleted);
|
||||
}
|
||||
RPC.call('editqueue', ['GroupPauseExtraPars', 0, '', checkedEditIDs], editCompleted);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -480,9 +473,6 @@ var Downloads = (new function($)
|
||||
}
|
||||
};
|
||||
|
||||
Util.show('#DownloadsDeleteConfirmDialog_Cleanup', Options.option('DeleteCleanupDisk') === 'yes');
|
||||
Util.show('#DownloadsDeleteConfirmDialog_Remain', Options.option('DeleteCleanupDisk') != 'yes');
|
||||
|
||||
ConfirmDialog.showModal('DownloadsDeleteConfirmDialog', deleteGroups);
|
||||
}
|
||||
|
||||
@@ -663,8 +653,6 @@ var DownloadsUI = (new function($)
|
||||
if (group.post.Log && group.post.Log.length > 0)
|
||||
{
|
||||
text = group.post.Log[group.post.Log.length-1].Text;
|
||||
// remove "for <nzb-name>" from label text
|
||||
text = text.replace(' for ' + group.NZBName, ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
460
webui/edit.js
460
webui/edit.js
@@ -26,9 +26,7 @@
|
||||
* In this module:
|
||||
* 1) Download edit dialog;
|
||||
* 2) Download multi edit dialog (edit multiple items);
|
||||
* 3) Download merge dialog;
|
||||
* 4) Download split dialog;
|
||||
* 5) History edit dialog.
|
||||
* 3) Download merge dialog.
|
||||
*/
|
||||
|
||||
/*** DOWNLOAD EDIT DIALOG ************************************************************/
|
||||
@@ -41,7 +39,6 @@ var DownloadsEditDialog = (new function($)
|
||||
var $DownloadsEditDialog;
|
||||
var $DownloadsLogTable;
|
||||
var $DownloadsFileTable;
|
||||
var $DownloadsEdit_ParamData;
|
||||
|
||||
// State
|
||||
var curGroup;
|
||||
@@ -55,7 +52,6 @@ var DownloadsEditDialog = (new function($)
|
||||
this.init = function()
|
||||
{
|
||||
$DownloadsEditDialog = $('#DownloadsEditDialog');
|
||||
$DownloadsEdit_ParamData = $('#DownloadsEdit_ParamData');
|
||||
|
||||
$('#DownloadsEdit_Save').click(saveChanges);
|
||||
$('#DownloadsEdit_Pause').click(itemPause);
|
||||
@@ -100,7 +96,6 @@ var DownloadsEditDialog = (new function($)
|
||||
// cleanup
|
||||
$DownloadsLogTable.fasttable('update', []);
|
||||
$DownloadsFileTable.fasttable('update', []);
|
||||
$DownloadsEdit_ParamData.empty();
|
||||
// resume updates
|
||||
Refresher.resume();
|
||||
});
|
||||
@@ -188,7 +183,8 @@ var DownloadsEditDialog = (new function($)
|
||||
$DownloadsLogTable.fasttable('update', []);
|
||||
$DownloadsFileTable.fasttable('update', []);
|
||||
|
||||
var postParamConfig = ParamTab.createPostParamConfig();
|
||||
var postParamConfig = Options.postParamConfig;
|
||||
defineBuiltinParams(postParamConfig);
|
||||
|
||||
Util.show('#DownloadsEdit_NZBNameReadonly', group.postprocess);
|
||||
Util.show('#DownloadsEdit_CancelPPGroup', group.postprocess);
|
||||
@@ -196,7 +192,7 @@ var DownloadsEditDialog = (new function($)
|
||||
Util.show('#DownloadsEdit_PauseGroup', !group.postprocess);
|
||||
Util.show('#DownloadsEdit_ResumeGroup', false);
|
||||
Util.show('#DownloadsEdit_Save', !group.postprocess);
|
||||
var postParam = postParamConfig[0].options.length > 0;
|
||||
var postParam = postParamConfig && postParamConfig.length > 0;
|
||||
var postLog = group.postprocess && group.post.Log.length > 0;
|
||||
Util.show('#DownloadsEdit_Param', postParam);
|
||||
Util.show('#DownloadsEdit_Log', postLog);
|
||||
@@ -224,7 +220,12 @@ var DownloadsEditDialog = (new function($)
|
||||
|
||||
if (postParam)
|
||||
{
|
||||
postParams = ParamTab.buildPostParamTab($DownloadsEdit_ParamData, postParamConfig, curGroup.Parameters);
|
||||
postParams = $.extend(true, [], postParamConfig);
|
||||
Options.mergeValues(postParams, group.Parameters);
|
||||
var content = Config.buildOptionsContent(postParams[0]);
|
||||
var configData = $('#DownloadsEdit_ParamData');
|
||||
configData.empty();
|
||||
configData.append(content);
|
||||
}
|
||||
|
||||
enableAllButtons();
|
||||
@@ -397,14 +398,7 @@ var DownloadsEditDialog = (new function($)
|
||||
notification = '#Notif_Downloads_Resumed';
|
||||
RPC.call('editqueue', ['GroupResume', 0, '', [curGroup.LastID]], function()
|
||||
{
|
||||
if (Options.option('ParCheck') === 'force')
|
||||
{
|
||||
completed();
|
||||
}
|
||||
else
|
||||
{
|
||||
RPC.call('editqueue', ['GroupPauseExtraPars', 0, '', [curGroup.LastID]], completed);
|
||||
}
|
||||
RPC.call('editqueue', ['GroupPauseExtraPars', 0, '', [curGroup.LastID]], completed);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -437,9 +431,53 @@ var DownloadsEditDialog = (new function($)
|
||||
|
||||
/*** TAB: POST-PROCESSING PARAMETERS **************************************************/
|
||||
|
||||
function defineBuiltinParams(postParamConfig)
|
||||
{
|
||||
if (Options.option('Unpack') !== 'yes')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (postParamConfig.length == 0)
|
||||
{
|
||||
postParamConfig.push({category: 'P', postparam: true, options: []});
|
||||
}
|
||||
|
||||
if (!Options.findOption(postParamConfig[0].options, '*Unpack:'))
|
||||
{
|
||||
postParamConfig[0].options.unshift({name: '*Unpack:Password', value: '', defvalue: '', select: [], caption: 'Password', description: 'Unpack-password for encrypted posts.'});
|
||||
postParamConfig[0].options.unshift({name: '*Unpack:', value: '', defvalue: 'yes', select: ['yes', 'no'], caption: 'Unpack', description: 'Set to "no" to disable unpack for this nzb-file.'});
|
||||
}
|
||||
}
|
||||
|
||||
function prepareParamRequest()
|
||||
{
|
||||
var request = [];
|
||||
for (var i=0; i < postParams.length; i++)
|
||||
{
|
||||
var section = postParams[i];
|
||||
for (var j=0; j < section.options.length; j++)
|
||||
{
|
||||
var option = section.options[j];
|
||||
if (!option.template && !section.hidden)
|
||||
{
|
||||
var oldValue = option.value;
|
||||
var newValue = Config.getOptionValue(option);
|
||||
if (oldValue != newValue && !(oldValue === '' && newValue === option.defvalue))
|
||||
{
|
||||
var opt = option.name + '=' + newValue;
|
||||
request.push(opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function saveParam()
|
||||
{
|
||||
var paramList = ParamTab.prepareParamRequest(postParams);
|
||||
var paramList = prepareParamRequest();
|
||||
saveNextParam(paramList);
|
||||
}
|
||||
|
||||
@@ -624,9 +662,6 @@ var DownloadsEditDialog = (new function($)
|
||||
var file = files[i];
|
||||
file.moved = false;
|
||||
}
|
||||
|
||||
var editIDList = [];
|
||||
var splitError = false;
|
||||
|
||||
for (var i = 0; i < files.length; i++)
|
||||
{
|
||||
@@ -640,8 +675,6 @@ var DownloadsEditDialog = (new function($)
|
||||
|
||||
if (checkedRows.indexOf(file.ID) > -1)
|
||||
{
|
||||
editIDList.push(file.ID);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case 'pause':
|
||||
@@ -694,28 +727,10 @@ var DownloadsEditDialog = (new function($)
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
case 'split':
|
||||
if (file.ActiveDownloads > 0 || file.FileSizeLo !== file.RemainingSizeLo)
|
||||
{
|
||||
splitError = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action === 'split')
|
||||
{
|
||||
if (splitError)
|
||||
{
|
||||
Notification.show('#Notif_Downloads_SplitNotPossible');
|
||||
}
|
||||
else
|
||||
{
|
||||
DownloadsSplitDialog.showModal(curGroup, editIDList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
filesLoaded(files);
|
||||
}
|
||||
|
||||
@@ -792,89 +807,6 @@ var DownloadsEditDialog = (new function($)
|
||||
}(jQuery));
|
||||
|
||||
|
||||
/*** PARAM TAB FOR EDIT DIALOGS ************************************************************/
|
||||
|
||||
var ParamTab = (new function($)
|
||||
{
|
||||
'use strict'
|
||||
|
||||
this.buildPostParamTab = function(configData, postParamConfig, parameters)
|
||||
{
|
||||
var postParams = $.extend(true, [], postParamConfig);
|
||||
Options.mergeValues(postParams, parameters);
|
||||
var content = Config.buildOptionsContent(postParams[0]);
|
||||
configData.empty();
|
||||
configData.append(content);
|
||||
configData.addClass('retain-margin');
|
||||
|
||||
var lastClass = '';
|
||||
var lastDiv = null;
|
||||
for (var i=0; i < configData.children().length; i++)
|
||||
{
|
||||
var div = $(configData.children()[i]);
|
||||
var divClass = div.attr('class');
|
||||
if (divClass != lastClass && lastClass != '')
|
||||
{
|
||||
lastDiv.addClass('wants-divider');
|
||||
}
|
||||
lastDiv = div;
|
||||
lastClass = divClass;
|
||||
}
|
||||
return postParams;
|
||||
}
|
||||
|
||||
this.createPostParamConfig = function()
|
||||
{
|
||||
var postParamConfig = Options.postParamConfig;
|
||||
defineBuiltinParams(postParamConfig);
|
||||
return postParamConfig;
|
||||
}
|
||||
|
||||
function defineBuiltinParams(postParamConfig)
|
||||
{
|
||||
if (Options.option('Unpack') !== 'yes')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (postParamConfig.length == 0)
|
||||
{
|
||||
postParamConfig.push({category: 'P', postparam: true, options: []});
|
||||
}
|
||||
|
||||
if (!Options.findOption(postParamConfig[0].options, '*Unpack:'))
|
||||
{
|
||||
postParamConfig[0].options.unshift({name: '*Unpack:Password', value: '', defvalue: '', select: [], caption: 'Password', sectionId: '_Unpack_', description: 'Unpack-password for encrypted archives.'});
|
||||
postParamConfig[0].options.unshift({name: '*Unpack:', value: '', defvalue: 'yes', select: ['yes', 'no'], caption: 'Unpack', sectionId: '_Unpack_', description: 'Unpack rar and 7-zip archives.'});
|
||||
}
|
||||
}
|
||||
|
||||
this.prepareParamRequest = function(postParams)
|
||||
{
|
||||
var request = [];
|
||||
for (var i=0; i < postParams.length; i++)
|
||||
{
|
||||
var section = postParams[i];
|
||||
for (var j=0; j < section.options.length; j++)
|
||||
{
|
||||
var option = section.options[j];
|
||||
if (!option.template && !section.hidden)
|
||||
{
|
||||
var oldValue = option.value;
|
||||
var newValue = Config.getOptionValue(option);
|
||||
if (oldValue != newValue && !(oldValue === '' && newValue === option.defvalue))
|
||||
{
|
||||
var opt = option.name + '=' + newValue;
|
||||
request.push(opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}(jQuery));
|
||||
|
||||
|
||||
/*** DOWNLOAD MULTI EDIT DIALOG ************************************************************/
|
||||
|
||||
var DownloadsMultiDialog = (new function($)
|
||||
@@ -1137,281 +1069,3 @@ var DownloadsMergeDialog = (new function($)
|
||||
Notification.show('#Notif_Downloads_Merged');
|
||||
}
|
||||
}(jQuery));
|
||||
|
||||
|
||||
/*** DOWNLOAD SPLIT DIALOG ************************************************************/
|
||||
|
||||
var DownloadsSplitDialog = (new function($)
|
||||
{
|
||||
'use strict'
|
||||
|
||||
// Controls
|
||||
var $DownloadsSplitDialog;
|
||||
|
||||
// State
|
||||
var splitEditIDList;
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
$DownloadsSplitDialog = $('#DownloadsSplitDialog');
|
||||
|
||||
$('#DownloadsSplit_Split').click(split);
|
||||
|
||||
$DownloadsSplitDialog.on('hidden', function ()
|
||||
{
|
||||
Refresher.resume();
|
||||
});
|
||||
|
||||
if (UISettings.setFocus)
|
||||
{
|
||||
$DownloadsSplitDialog.on('shown', function ()
|
||||
{
|
||||
$('#DownloadsSplit_Merge').focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.showModal = function(group, editIDList)
|
||||
{
|
||||
Refresher.pause();
|
||||
splitEditIDList = editIDList;
|
||||
var groupName = group.NZBName + ' (' + editIDList[0] + (editIDList.length > 1 ? '-' + editIDList[editIDList.length-1] : '') + ')';
|
||||
$('#DownloadsSplit_NZBName').attr('value', groupName);
|
||||
$DownloadsSplitDialog.modal({backdrop: 'static'});
|
||||
}
|
||||
|
||||
function split()
|
||||
{
|
||||
var groupName = $('#DownloadsSplit_NZBName').val();
|
||||
RPC.call('editqueue', ['FileSplit', 0, groupName, splitEditIDList], completed);
|
||||
}
|
||||
|
||||
function completed(result)
|
||||
{
|
||||
$('#DownloadsEditDialog').modal('hide');
|
||||
$DownloadsSplitDialog.modal('hide');
|
||||
Refresher.update();
|
||||
Notification.show(result ? '#Notif_Downloads_Splitted' : '#Notif_Downloads_SplitError');
|
||||
}
|
||||
}(jQuery));
|
||||
|
||||
|
||||
/*** EDIT HISTORY DIALOG *************************************************************************/
|
||||
|
||||
var HistoryEditDialog = (new function()
|
||||
{
|
||||
'use strict'
|
||||
|
||||
// Controls
|
||||
var $HistoryEditDialog;
|
||||
var $HistoryEdit_ParamData;
|
||||
|
||||
// State
|
||||
var curHist;
|
||||
var notification = null;
|
||||
var postParams = [];
|
||||
var lastPage;
|
||||
var lastFullscreen;
|
||||
var saveParamCompleted;
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
$HistoryEditDialog = $('#HistoryEditDialog');
|
||||
$HistoryEdit_ParamData = $('#HistoryEdit_ParamData');
|
||||
|
||||
$('#HistoryEdit_Save').click(saveChanges);
|
||||
$('#HistoryEdit_Delete').click(itemDelete);
|
||||
$('#HistoryEdit_Return').click(itemReturn);
|
||||
$('#HistoryEdit_Reprocess').click(itemReprocess);
|
||||
$('#HistoryEdit_Param').click(tabClick);
|
||||
$('#HistoryEdit_Back').click(backClick);
|
||||
|
||||
$HistoryEditDialog.on('hidden', function ()
|
||||
{
|
||||
$HistoryEdit_ParamData.empty();
|
||||
// resume updates
|
||||
Refresher.resume();
|
||||
});
|
||||
|
||||
TabDialog.extend($HistoryEditDialog);
|
||||
}
|
||||
|
||||
this.showModal = function(hist)
|
||||
{
|
||||
Refresher.pause();
|
||||
|
||||
curHist = hist;
|
||||
|
||||
var status;
|
||||
if (hist.Kind === 'URL')
|
||||
{
|
||||
status = HistoryUI.buildStatus(hist.status, '');
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HistoryUI.buildStatus(hist.ParStatus, 'Par: ') + ' ' +
|
||||
(Options.option('Unpack') == 'yes' || hist.UnpackStatus != 'NONE' ? HistoryUI.buildStatus(hist.UnpackStatus, 'Unpack: ') + ' ' : '') +
|
||||
(hist.MoveStatus === "FAILURE" ? HistoryUI.buildStatus(hist.MoveStatus, 'Move: ') + ' ' : "");
|
||||
for (var i=0; i<hist.ScriptStatuses.length; i++)
|
||||
{
|
||||
var scriptStatus = hist.ScriptStatuses[i];
|
||||
status += HistoryUI.buildStatus(scriptStatus.Status, Options.shortScriptName(scriptStatus.Name) + ': ') + ' ';
|
||||
}
|
||||
}
|
||||
|
||||
$('#HistoryEdit_Title').text(Util.formatNZBName(hist.Name));
|
||||
if (hist.Kind === 'URL')
|
||||
{
|
||||
$('#HistoryEdit_Title').html($('#HistoryEdit_Title').html() + ' ' + '<span class="label label-info">URL</span>');
|
||||
}
|
||||
|
||||
$('#HistoryEdit_Status').html(status);
|
||||
$('#HistoryEdit_Category').text(hist.Category !== '' ? hist.Category : '<empty>');
|
||||
$('#HistoryEdit_Path').text(hist.DestDir);
|
||||
|
||||
var size = Util.formatSizeMB(hist.FileSizeMB, hist.FileSizeLo);
|
||||
|
||||
var table = '';
|
||||
table += '<tr><td>Total</td><td class="text-right">' + size + '</td></tr>';
|
||||
table += '<tr><td>Files (total/parked)</td><td class="text-right">' + hist.FileCount + '/' + hist.RemainingFileCount + '</td></tr>';
|
||||
$('#HistoryEdit_Statistics').html(table);
|
||||
|
||||
Util.show($('#HistoryEdit_ReturnGroup'), hist.RemainingFileCount > 0 || hist.Kind === 'URL');
|
||||
Util.show($('#HistoryEdit_PathGroup, #HistoryEdit_StatisticsGroup, #HistoryEdit_ReprocessGroup'), hist.Kind === 'NZB');
|
||||
|
||||
var postParamConfig = ParamTab.createPostParamConfig();
|
||||
var postParam = hist.Kind === 'NZB' && postParamConfig[0].options.length > 0;
|
||||
Util.show('#HistoryEdit_Param', postParam);
|
||||
Util.show('#HistoryEdit_Save', postParam);
|
||||
$('#HistoryEdit_Close').toggleClass('btn-primary', !postParam);
|
||||
|
||||
if (postParam)
|
||||
{
|
||||
postParams = ParamTab.buildPostParamTab($HistoryEdit_ParamData, postParamConfig, curHist.Parameters);
|
||||
}
|
||||
|
||||
enableAllButtons();
|
||||
|
||||
$('#HistoryEdit_GeneralTab').show();
|
||||
$('#HistoryEdit_ParamTab').hide();
|
||||
$('#HistoryEdit_Back').hide();
|
||||
$('#HistoryEdit_BackSpace').show();
|
||||
$HistoryEditDialog.restoreTab();
|
||||
|
||||
notification = null;
|
||||
|
||||
$HistoryEditDialog.modal({backdrop: 'static'});
|
||||
}
|
||||
|
||||
function tabClick(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
$('#HistoryEdit_Back').fadeIn(500);
|
||||
$('#HistoryEdit_BackSpace').hide();
|
||||
var tab = '#' + $(this).attr('data-tab');
|
||||
lastPage = $(tab);
|
||||
lastFullscreen = ($(this).attr('data-fullscreen') === 'true') && !UISettings.miniTheme;
|
||||
|
||||
$HistoryEditDialog.switchTab($('#HistoryEdit_GeneralTab'), lastPage,
|
||||
e.shiftKey || !UISettings.slideAnimation ? 0 : 500,
|
||||
{fullscreen: lastFullscreen, mini: UISettings.miniTheme});
|
||||
}
|
||||
|
||||
function backClick(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
$('#HistoryEdit_Back').fadeOut(500, function()
|
||||
{
|
||||
$('#HistoryEdit_BackSpace').show();
|
||||
});
|
||||
|
||||
$HistoryEditDialog.switchTab(lastPage, $('#HistoryEdit_GeneralTab'),
|
||||
e.shiftKey || !UISettings.slideAnimation ? 0 : 500,
|
||||
{fullscreen: lastFullscreen, mini: UISettings.miniTheme, back: true});
|
||||
}
|
||||
|
||||
function disableAllButtons()
|
||||
{
|
||||
$('#HistoryEditDialog .modal-footer .btn').attr('disabled', 'disabled');
|
||||
setTimeout(function()
|
||||
{
|
||||
$('#HistoryEdit_Transmit').show();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function enableAllButtons()
|
||||
{
|
||||
$('#HistoryEditDialog .modal-footer .btn').removeAttr('disabled');
|
||||
$('#HistoryEdit_Transmit').hide();
|
||||
}
|
||||
|
||||
function itemDelete()
|
||||
{
|
||||
disableAllButtons();
|
||||
notification = '#Notif_History_Deleted';
|
||||
RPC.call('editqueue', ['HistoryDelete', 0, '', [curHist.ID]], completed);
|
||||
}
|
||||
|
||||
function itemReturn()
|
||||
{
|
||||
disableAllButtons();
|
||||
notification = '#Notif_History_Returned';
|
||||
RPC.call('editqueue', ['HistoryReturn', 0, '', [curHist.ID]], completed);
|
||||
}
|
||||
|
||||
function itemReprocess()
|
||||
{
|
||||
disableAllButtons();
|
||||
saveParam(function()
|
||||
{
|
||||
notification = '#Notif_History_Reproces';
|
||||
RPC.call('editqueue', ['HistoryProcess', 0, '', [curHist.ID]], completed);
|
||||
});
|
||||
}
|
||||
|
||||
function completed()
|
||||
{
|
||||
$HistoryEditDialog.modal('hide');
|
||||
Refresher.update();
|
||||
if (notification)
|
||||
{
|
||||
Notification.show(notification);
|
||||
notification = null;
|
||||
}
|
||||
}
|
||||
|
||||
function saveChanges()
|
||||
{
|
||||
disableAllButtons();
|
||||
notification = null;
|
||||
saveParam(completed);
|
||||
}
|
||||
|
||||
/*** TAB: POST-PROCESSING PARAMETERS **************************************************/
|
||||
|
||||
function saveParam(_saveParamCompleted)
|
||||
{
|
||||
saveParamCompleted = _saveParamCompleted;
|
||||
var paramList = ParamTab.prepareParamRequest(postParams);
|
||||
saveNextParam(paramList);
|
||||
}
|
||||
|
||||
function saveNextParam(paramList)
|
||||
{
|
||||
if (paramList.length > 0)
|
||||
{
|
||||
RPC.call('editqueue', ['HistorySetParameter', 0, paramList[0], [curHist.ID]], function()
|
||||
{
|
||||
notification = '#Notif_History_Saved';
|
||||
paramList.shift();
|
||||
saveNextParam(paramList);
|
||||
})
|
||||
}
|
||||
else
|
||||
{
|
||||
saveParamCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
}(jQuery));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2012-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -192,7 +192,7 @@
|
||||
pageDots : Util.parseBool(config.pageDots),
|
||||
curPage : 1,
|
||||
checkedRows: [],
|
||||
lastClickedRowID: null
|
||||
lastClickedRowID: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -227,11 +227,6 @@
|
||||
return $(this).data('fasttable').checkedRows;
|
||||
},
|
||||
|
||||
checkRow : function(id, checked)
|
||||
{
|
||||
checkRow($(this).data('fasttable'), id, checked);
|
||||
},
|
||||
|
||||
itemCheckClick : itemCheckClick,
|
||||
|
||||
titleCheckClick : titleCheckClick
|
||||
@@ -629,7 +624,7 @@
|
||||
var id = row.fasttableID;
|
||||
var doToggle = true;
|
||||
|
||||
if (event.shiftKey && data.lastClickedRowID != null)
|
||||
if (event.shiftKey && data.lastClickedRowID > 0)
|
||||
{
|
||||
var checked = checkedRows.indexOf(id) > -1;
|
||||
doToggle = !checkRange(data, id, data.lastClickedRowID, !checked);
|
||||
@@ -661,7 +656,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
data.lastClickedRowID = null;
|
||||
data.lastClickedRowID = 0;
|
||||
checkAll(data, !hasSelectedItems);
|
||||
}
|
||||
|
||||
|
||||
226
webui/history.js
226
webui/history.js
@@ -25,15 +25,15 @@
|
||||
/*
|
||||
* In this module:
|
||||
* 1) History tab;
|
||||
* 2) Functions for html generation for history, also used from other modules (edit dialog).
|
||||
* 2) History edit dialog.
|
||||
*/
|
||||
|
||||
|
||||
/*** HISTORY TAB AND EDIT HISTORY DIALOG **********************************************/
|
||||
|
||||
|
||||
var History = (new function($)
|
||||
{
|
||||
'use strict';
|
||||
|
||||
|
||||
// Controls
|
||||
var $HistoryTable;
|
||||
var $HistoryTabBadge;
|
||||
@@ -53,6 +53,8 @@ var History = (new function($)
|
||||
$HistoryTabBadge = $('#HistoryTabBadge');
|
||||
$HistoryTabBadgeEmpty = $('#HistoryTabBadgeEmpty');
|
||||
$HistoryRecordsPerPage = $('#HistoryRecordsPerPage');
|
||||
|
||||
historyEditDialog.init();
|
||||
|
||||
var recordsPerPage = UISettings.read('HistoryRecordsPerPage', 10);
|
||||
$HistoryRecordsPerPage.val(recordsPerPage);
|
||||
@@ -113,11 +115,7 @@ var History = (new function($)
|
||||
{
|
||||
if (hist.ParStatus == 'FAILURE' || hist.UnpackStatus == 'FAILURE' || hist.MoveStatus == 'FAILURE' || hist.ScriptStatus == 'FAILURE')
|
||||
{
|
||||
hist.status = 'failure';
|
||||
}
|
||||
else if (hist.ParStatus == 'MANUAL')
|
||||
{
|
||||
hist.status = 'damaged';
|
||||
hist.status = 'failure';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -192,7 +190,7 @@ var History = (new function($)
|
||||
{
|
||||
var hist = item.hist;
|
||||
|
||||
var status = HistoryUI.buildStatus(hist.status, '');
|
||||
var status = buildStatus(hist.status, '');
|
||||
|
||||
var name = '<a href="#" histid="' + hist.ID + '">' + Util.textToHtml(Util.formatNZBName(hist.Name)) + '</a>';
|
||||
var category = Util.textToHtml(hist.Category);
|
||||
@@ -234,6 +232,30 @@ var History = (new function($)
|
||||
}
|
||||
}
|
||||
|
||||
function buildStatus(status, prefix)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case 'success':
|
||||
case 'SUCCESS':
|
||||
return '<span class="label label-status label-success">' + prefix + 'success</span>';
|
||||
case 'failure':
|
||||
case 'FAILURE':
|
||||
return '<span class="label label-status label-important">' + prefix + 'failure</span>';
|
||||
case 'unknown':
|
||||
case 'UNKNOWN':
|
||||
return '<span class="label label-status label-info">' + prefix + 'unknown</span>';
|
||||
case 'repairable':
|
||||
case 'REPAIR_POSSIBLE':
|
||||
return '<span class="label label-status label-success">' + prefix + 'repairable</span>';
|
||||
case 'none':
|
||||
case 'NONE':
|
||||
return '<span class="label label-status">' + prefix + 'none</span>';
|
||||
default:
|
||||
return '<span class="label label-status">' + prefix + status + '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
this.recordsPerPageChange = function()
|
||||
{
|
||||
var val = $HistoryRecordsPerPage.val();
|
||||
@@ -303,66 +325,138 @@ var History = (new function($)
|
||||
notification = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function editClick()
|
||||
{
|
||||
var histid = $(this).attr('histid');
|
||||
$(this).blur();
|
||||
|
||||
var hist = null;
|
||||
|
||||
// find history object
|
||||
for (var i=0; i<history.length; i++)
|
||||
{
|
||||
var gr = history[i];
|
||||
if (gr.ID == histid)
|
||||
{
|
||||
hist = gr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hist == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HistoryEditDialog.showModal(hist);
|
||||
}
|
||||
}(jQuery));
|
||||
|
||||
|
||||
/*** FUNCTIONS FOR HTML GENERATION (also used from other modules) *****************************/
|
||||
|
||||
var HistoryUI = (new function($)
|
||||
{
|
||||
'use strict';
|
||||
|
||||
this.buildStatus = function(status, prefix)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case 'success':
|
||||
case 'SUCCESS':
|
||||
return '<span class="label label-status label-success">' + prefix + 'success</span>';
|
||||
case 'failure':
|
||||
case 'FAILURE':
|
||||
return '<span class="label label-status label-important">' + prefix + 'failure</span>';
|
||||
case 'unknown':
|
||||
case 'UNKNOWN':
|
||||
return '<span class="label label-status label-info">' + prefix + 'unknown</span>';
|
||||
case 'repairable':
|
||||
case 'REPAIR_POSSIBLE':
|
||||
return '<span class="label label-status label-success">' + prefix + 'repairable</span>';
|
||||
case 'manual':
|
||||
case 'MANUAL':
|
||||
case 'damaged':
|
||||
return '<span class="label label-status label-warning">' + prefix + status + '</span>';
|
||||
case 'none':
|
||||
case 'NONE':
|
||||
return '<span class="label label-status">' + prefix + 'none</span>';
|
||||
default:
|
||||
return '<span class="label label-status">' + prefix + status + '</span>';
|
||||
}
|
||||
historyEditDialog.showModal(histid);
|
||||
}
|
||||
|
||||
/*** EDIT HISTORY DIALOG *************************************************************************/
|
||||
|
||||
var historyEditDialog = new function()
|
||||
{
|
||||
// Controls
|
||||
var $HistoryEditDialog;
|
||||
|
||||
// State
|
||||
var curHist;
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
$HistoryEditDialog = $('#HistoryEditDialog');
|
||||
|
||||
$('#HistoryEdit_Delete').click(itemDelete);
|
||||
$('#HistoryEdit_Return').click(itemReturn);
|
||||
$('#HistoryEdit_Reprocess').click(itemReprocess);
|
||||
|
||||
$HistoryEditDialog.on('hidden', function () {
|
||||
Refresher.resume();
|
||||
});
|
||||
}
|
||||
|
||||
this.showModal = function(histid)
|
||||
{
|
||||
var hist = null;
|
||||
|
||||
// find history object
|
||||
for (var i=0; i<history.length; i++)
|
||||
{
|
||||
var gr = history[i];
|
||||
if (gr.ID == histid)
|
||||
{
|
||||
hist = gr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hist == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Refresher.pause();
|
||||
|
||||
curHist = hist;
|
||||
|
||||
var status;
|
||||
if (hist.Kind === 'URL')
|
||||
{
|
||||
status = buildStatus(hist.status, '');
|
||||
}
|
||||
else
|
||||
{
|
||||
status = buildStatus(hist.ParStatus, 'Par: ') + ' ' +
|
||||
(Options.option('Unpack') == 'yes' || hist.UnpackStatus != 'NONE' ? buildStatus(hist.UnpackStatus, 'Unpack: ') + ' ' : '') +
|
||||
(hist.MoveStatus === "FAILURE" ? buildStatus(hist.MoveStatus, 'Move: ') + ' ' : "") +
|
||||
buildStatus(hist.ScriptStatus, 'Script: ');
|
||||
}
|
||||
|
||||
$('#HistoryEdit_Title').text(Util.formatNZBName(hist.Name));
|
||||
if (hist.Kind === 'URL')
|
||||
{
|
||||
$('#HistoryEdit_Title').html($('#HistoryEdit_Title').html() + ' ' + '<span class="label label-info">URL</span>');
|
||||
}
|
||||
|
||||
$('#HistoryEdit_Status').html(status);
|
||||
$('#HistoryEdit_Category').text(hist.Category !== '' ? hist.Category : '<empty>');
|
||||
$('#HistoryEdit_Path').text(hist.DestDir);
|
||||
|
||||
var size = Util.formatSizeMB(hist.FileSizeMB, hist.FileSizeLo);
|
||||
|
||||
var table = '';
|
||||
table += '<tr><td>Total</td><td class="text-right">' + size + '</td></tr>';
|
||||
table += '<tr><td>Files (total/parked)</td><td class="text-right">' + hist.FileCount + '/' + hist.RemainingFileCount + '</td></tr>';
|
||||
$('#HistoryEdit_Statistics').html(table);
|
||||
|
||||
Util.show($('#HistoryEdit_ReturnGroup'), hist.RemainingFileCount > 0 || hist.Kind === 'URL');
|
||||
Util.show($('#HistoryEdit_PathGroup, #HistoryEdit_StatisticsGroup, #HistoryEdit_ReprocessGroup'), hist.Kind === 'NZB');
|
||||
|
||||
enableAllButtons();
|
||||
|
||||
$HistoryEditDialog.modal({backdrop: 'static'});
|
||||
}
|
||||
|
||||
function disableAllButtons()
|
||||
{
|
||||
$('#HistoryEditDialog .modal-footer .btn').attr('disabled', 'disabled');
|
||||
setTimeout(function()
|
||||
{
|
||||
$('#HistoryEdit_Transmit').show();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function enableAllButtons()
|
||||
{
|
||||
$('#HistoryEditDialog .modal-footer .btn').removeAttr('disabled');
|
||||
$('#HistoryEdit_Transmit').hide();
|
||||
}
|
||||
|
||||
function itemDelete()
|
||||
{
|
||||
disableAllButtons();
|
||||
notification = '#Notif_History_Deleted';
|
||||
RPC.call('editqueue', ['HistoryDelete', 0, '', [curHist.ID]], completed);
|
||||
}
|
||||
|
||||
function itemReturn()
|
||||
{
|
||||
disableAllButtons();
|
||||
notification = '#Notif_History_Returned';
|
||||
RPC.call('editqueue', ['HistoryReturn', 0, '', [curHist.ID]], completed);
|
||||
}
|
||||
|
||||
function itemReprocess()
|
||||
{
|
||||
disableAllButtons();
|
||||
notification = '#Notif_History_Reproces';
|
||||
RPC.call('editqueue', ['HistoryProcess', 0, '', [curHist.ID]], completed);
|
||||
}
|
||||
|
||||
function completed()
|
||||
{
|
||||
$HistoryEditDialog.modal('hide');
|
||||
editCompleted();
|
||||
}
|
||||
}();
|
||||
}(jQuery));
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 54 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
339
webui/index.html
339
webui/index.html
@@ -127,7 +127,7 @@
|
||||
<li class="menu-header">Automatic refresh</li>
|
||||
<li data="0.1"><a href="#"><table><tr><td></td><td>0.1</td><td>Second</td></tr></table></a></li>
|
||||
<li data="0.2"><a href="#"><table><tr><td></td><td>0.2</td><td>Second</td></tr></table></a></li>
|
||||
<li data="0.5"><a href="#"><table><tr><td></td><td>0.5</td><td>Second</td></tr></table></a></li>
|
||||
<li data="0.5"><a href="#"><table><tr><td></td></i><td>0.5</td><td>Second</td></tr></table></a></li>
|
||||
<li data="1"><a href="#"><table><tr><td></td><td>1</td><td>Second</td></tr></table></a></li>
|
||||
<li data="5"><a href="#"><table><tr><td></td><td>5</td><td>Seconds</td></tr></table></a></li>
|
||||
<li data="15"><a href="#"><table><tr><td></td><td>15</td><td>Seconds</td></tr></table></a></li>
|
||||
@@ -181,12 +181,8 @@
|
||||
<p id="ErrorAlert-text"></p>
|
||||
</div>
|
||||
|
||||
<!-- *** ERROR BLOCK ****************************************************************** -->
|
||||
<div id="RefreshError" data-duration="1000" style="display:none" class="alert alert-inverse alert-center alert-center-small hide">
|
||||
<strong>Communication error, retrying...</strong>
|
||||
</div>
|
||||
|
||||
<!-- *** INIT LOADING-ALERT ************************************************************ -->
|
||||
|
||||
<div class="alert alert-info alert-block" id="FirstUpdateInfo">
|
||||
<h4 class="alert-heading">Loading...</h4>
|
||||
Please wait.
|
||||
@@ -404,16 +400,17 @@
|
||||
</div>
|
||||
<div class="alert alert-error alert-block hide" id="ConfigLoadServerTemplateError">
|
||||
<h4 class="alert-heading">Loading configuration failed</h4>
|
||||
Could not load template configuration file <em>nzbget.conf</em>. The file contains descriptions of options
|
||||
and is needed to display settings page. The file comes with NZBGet distribution archive and is usually
|
||||
automaically installed into the right location. This seems not to be a case with your installation though.<br><br>
|
||||
|
||||
<span id="ConfigLoadServerTemplateErrorEmpty">Please put the template configuration file <em>nzbget.conf</em> into the
|
||||
directory with web-interface files (<em><span id="ConfigLoadServerTemplateErrorWebDir"></span></em>).</span>
|
||||
|
||||
<span id="ConfigLoadServerTemplateErrorNotFound">Please edit your configuration file
|
||||
(<em><span id="ConfigLoadServerTemplateErrorConfigFile"></span></em>) in a text editor
|
||||
and set the option <em>ConfigTemplate</em> to point to the template configuration file <em>nzbget.conf</em>.</span>
|
||||
Could not load template configuration file <em>nzbget.conf</em>. NZBGet reads the description of options from this file.
|
||||
Please put the file <em>nzbget.conf</em> which comes with the distribution archive of NZBGet into webui-directory
|
||||
(option <em>WebDir</em>).
|
||||
Do not put your actual configuration file but rather the unchanged original file.
|
||||
</div>
|
||||
<div class="alert alert-error alert-block hide" id="ConfigLoadPostTemplateError">
|
||||
<h4 class="alert-heading">Loading configuration of post-processing script failed</h4>
|
||||
Could not load template post-processing configuration file <em class="ConfigLoadPostTemplateErrorFilename"></em>. NZBGet reads the description of options from this file.
|
||||
Please put the file <em class="ConfigLoadPostTemplateErrorFilename"></em> which comes with the post-processing script into webui-directory
|
||||
(option <em>WebDir</em>).
|
||||
Do not put your actual configuration file but rather the unchanged original file.
|
||||
</div>
|
||||
<div class="alert alert-error alert-block hide" id="ConfigLoadError">
|
||||
<h4 class="alert-heading">Loading configuration failed</h4>
|
||||
@@ -450,14 +447,22 @@
|
||||
<div id="ConfigInfo">
|
||||
<p>
|
||||
On this page you can review and change settings. When you done with changes click
|
||||
<em><strong>Save all changes</strong></em>, which saves the changes made in all sections.
|
||||
It's not neccessary to save changes in each section individually.
|
||||
<em><strong>Save all changes</strong></em>, which will save the changes made on all pages.
|
||||
It's not neccessary to save the changes on each page individually.
|
||||
</p>
|
||||
|
||||
<p>The configuration consists of two parts:
|
||||
<ul>
|
||||
<li>NZBGet settings</li>
|
||||
<li>Post-processing script settings</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h4>NZBGet settings</h4>
|
||||
<p>
|
||||
When you configure NZBGet for the first time you need
|
||||
With these settings you configure NZBGet. When you configure NZBGet for the first time you need
|
||||
to check at least the option <a class="option" href="#" data-category="S" onclick="Config.scrollToOption(event, this)">MainDir</a> and configure one news server.
|
||||
Any changes of NZBGet settings require a restart or reload (soft-restart) of NZBGet.
|
||||
</p>
|
||||
<p>
|
||||
There are many configuration options affecting performance. If you use
|
||||
@@ -466,18 +471,20 @@
|
||||
performance - see <a href="http://nzbget.sourceforge.net/Performance_tips">Performance tips</a>.
|
||||
</p>
|
||||
|
||||
<h4>Post-processing scripts settings</h4>
|
||||
<h4>Post-processing script settings</h4>
|
||||
<p>
|
||||
When NZBGet finishes download of a nzb-file it can execute post-processing scripts for further processing (cleanup, etc.).
|
||||
To configure scripts use options in section <em><strong>POST-PROCESSING SCRIPTS</strong></em>.
|
||||
When NZBGet finishes download
|
||||
of nzb-file it can start a post-processing script for further processing (cleanup, etc.).
|
||||
You can configure what script must be executed using option <a class="option" href="#" data-category="S" onclick="Config.scrollToOption(event, this)">PostProcess</a>
|
||||
in section <em><strong>POST-PROCESSING</strong></em>.
|
||||
</p>
|
||||
<p>
|
||||
If your post-processing scripts define own options they are also shown here and can be configured like NZBGets built-in options.
|
||||
</p>
|
||||
|
||||
<h4>Backup and restore settings</h4>
|
||||
<p>
|
||||
This can be done in section <em><strong>SYSTEM</strong></em>.
|
||||
The post-processing script settings are shown on the navigation bar
|
||||
only if you have setup a post-processing script and if it has a configuration file. For your convenience
|
||||
NZBGet proivides you with a way to configure the post-processing script options via web-interface.
|
||||
These settings however do not
|
||||
have any effect on NZBGet but rather on the post-processing script only. The changes made here are in
|
||||
effect after saving for the next post-processing job started by NZBGet. A restart of NZBGet is not required.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -497,16 +504,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="control-group config-static config-system">
|
||||
<label class="control-label nowrap">Backup Settings</label>
|
||||
<div class="controls">
|
||||
<button type="button" class="btn" onclick="ConfigBackupRestore.backupSettings()">Backup</button>
|
||||
<button type="button" class="btn" onclick="TODO()">Backup</button>
|
||||
<p class="help-block">
|
||||
<span class="help-option-title">Save settings to a local file.</span><br><br>
|
||||
<span class="help-option-title">Save settings to local file.</span><br><br>
|
||||
Export all settings for backup purpose.
|
||||
<span id="ConfigBackupSafariNote"><br><br>
|
||||
<span class="label label-warning">NOTE:</span>
|
||||
This works with all major browsers except Safari (tested with 6.0.4; may work with newer versions).</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -514,14 +519,14 @@
|
||||
<div class="control-group config-static config-system">
|
||||
<label class="control-label nowrap">Restore Settings</label>
|
||||
<div class="controls">
|
||||
<button type="button" class="btn" onclick="ConfigBackupRestore.restoreSettings()">Restore</button>
|
||||
<input type="file" id="Config_RestoreInput" class="hidden-file-input">
|
||||
<button type="button" class="btn" onclick="TODO()">Restore</button>
|
||||
<p class="help-block">
|
||||
<span class="help-option-title">Load settings from a local file.</span><br><br>
|
||||
Import settings from a previously created backup file. You can restore the whole configuration file or choose individual sections.
|
||||
<span class="help-option-title">Load settings from local file.</span><br><br>
|
||||
Import all settings from a perviously created backup file.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
@@ -568,7 +573,7 @@
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>For more info please visit <a href="http://nzbget.sourceforge.net">NZBGet Home Page</a>. Among other things the developers of third-party apps find there complete docs about RPC interface.</p>
|
||||
<p>Should you need help, have suggestions or want to share your improvements - <a href="http://nzbget.sourceforge.net/forum">NZBGet Forum</a> is a place to do that.</p>
|
||||
<p>Should you need help, have suggestions or want to share your improvements - <a href="http://sourceforge.net/apps/phpbb/nzbget/">NZBGet Forum</a> is a place to do that.</p>
|
||||
<p>If you use NZBGet on a media player, router, NAS or other non-PC device the best place to get help is probably forums specialized on your device.</p>
|
||||
|
||||
<h1>Information about included libraries</h1>
|
||||
@@ -760,12 +765,10 @@
|
||||
<button class="btn" onclick="DownloadsEditDialog.editActionClick('pause')" title="Pause selected files"><i class="icon-pause"></i><span class="btn-caption"> Pause</span></button>
|
||||
<button class="btn" onclick="DownloadsEditDialog.editActionClick('resume')" title="Resume selected files"><i class="icon-play"></i><span class="btn-caption"> Resume</span></button>
|
||||
<button class="btn" onclick="DownloadsEditDialog.editActionClick('delete')" title="Delete selected files"><i class="icon-trash"></i><span class="btn-caption"> Delete</span></button>
|
||||
<button class="btn" onclick="DownloadsEditDialog.editActionClick('split')" title="Split selected files into new download"><i class="icon-split"></i><span class="btn-caption"> Split</span></button>
|
||||
</div>
|
||||
<div class="btn-group phone-only inline"><button class="btn" onclick="DownloadsEditDialog.editActionClick('pause')" title="Pause selected files"><i class="icon-pause"></i><span class="btn-caption"> Pause</span></button></div>
|
||||
<div class="btn-group phone-only inline"><button class="btn" onclick="DownloadsEditDialog.editActionClick('resume')" title="Resume selected files"><i class="icon-play"></i><span class="btn-caption"> Resume</span></button></div>
|
||||
<div class="btn-group phone-only inline"><button class="btn" onclick="DownloadsEditDialog.editActionClick('delete')" title="Delete selected files"><i class="icon-trash"></i><span class="btn-caption"> Delete</span></button></div>
|
||||
<div class="btn-group phone-only inline"><button class="btn" onclick="DownloadsEditDialog.editActionClick('split')" title="Split selected files into new download"><i class="icon-split"></i><span class="btn-caption"> Split</span></button></div>
|
||||
|
||||
<!-- MOVE BUTTONS -->
|
||||
<div class="btn-group phone-hide">
|
||||
@@ -963,40 +966,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- *** SPLIT DOWNLOAD DIALOG ************************************************************ -->
|
||||
|
||||
<div class="modal modal-padded hide" id="DownloadsSplitDialog">
|
||||
<div class="modal-header">
|
||||
<a class="close" href='#' data-dismiss="modal"><i class="icon-close"></i></a>
|
||||
<h3>Split Download</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-vertical">
|
||||
<fieldset>
|
||||
<p>New download will be created from selected files. Please choose the name for new download.</p>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls" id="DownloadsSplit_NZBNameGroup">
|
||||
<input type="text" class="input-xxlarge" id="DownloadsSplit_NZBName" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="help-block" style="margin-top:10px;">The new download inherits
|
||||
all other properties such as category, priority, etc. from the source item.
|
||||
This action closes the download-edit-dialog. Any changes made in the dialog are not saved.</p>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="dialog-transmit hide" style="position:absolute;margin-left:260px;" id="DownloadsSplit_Transmit"><img src="img/transmit.gif"></div>
|
||||
<a href="#" class="btn" data-dismiss="modal">Close</a>
|
||||
<a href="#" class="btn btn-primary" id="DownloadsSplit_Split">Split</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- *** QUICK HELP: Configure Categores ************************************************** -->
|
||||
|
||||
<div class="modal modal-mini modal-center hide" id="ConfigureCategoriesHelp">
|
||||
@@ -1014,76 +983,51 @@
|
||||
<div class="modal hide" id="HistoryEditDialog">
|
||||
<div class="modal-header">
|
||||
<a class="close" href='#' data-dismiss="modal"><i class="icon-close"></i></a>
|
||||
<a class="back" id="HistoryEdit_Back" href="#" title="Back"><i class="icon-back"></i></a>
|
||||
<a class="back back-hidden" id="HistoryEdit_BackSpace"><i class="icon-hidden"></i></a>
|
||||
<h3 id="HistoryEdit_Title"></h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<div class="modal-tab" id="HistoryEdit_GeneralTab">
|
||||
<div class="form-horizontal">
|
||||
<fieldset>
|
||||
<div class="form-horizontal">
|
||||
<fieldset>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="HistoryEdit_Status">Status</label>
|
||||
<div class="controls" style="margin-top: 4px;">
|
||||
<span id="HistoryEdit_Status"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="HistoryEdit_Category">Category</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input" id="HistoryEdit_Category"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="HistoryEdit_PathGroup">
|
||||
<label class="control-label" for="HistoryEdit_Path">Download Path</label>
|
||||
<div class="controls">
|
||||
<span class="uneditable-mulitline-input" id="HistoryEdit_Path"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group control-group-last" id="HistoryEdit_StatisticsGroup">
|
||||
<label class="control-label" for="HistoryEdit_Statistics">Statistics</label>
|
||||
<div class="controls">
|
||||
<table class="table table-striped table-bordered data-statistics">
|
||||
<tbody id="HistoryEdit_Statistics">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="modal-bottom-toolbar">
|
||||
<button class="btn" data-tab="HistoryEdit_ParamTab" id="HistoryEdit_Param" title="Post-processing parameters">PP-Parameters <i class="icon-forward" style="opacity:0.6;"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="HistoryEdit_Status">Status</label>
|
||||
<div class="controls" style="margin-top: 4px;">
|
||||
<span id="HistoryEdit_Status"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-tab hide" id="HistoryEdit_ParamTab">
|
||||
<div class="form-horizontal">
|
||||
<fieldset id="HistoryEdit_ParamData">
|
||||
</fieldset>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="HistoryEdit_Category">Category</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input" id="HistoryEdit_Category"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" id="HistoryEdit_PathGroup">
|
||||
<label class="control-label" for="HistoryEdit_Path">Download Path</label>
|
||||
<div class="controls">
|
||||
<span class="uneditable-mulitline-input" id="HistoryEdit_Path"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" style="margin-top: 15px; margin-bottom:0;" id="HistoryEdit_StatisticsGroup">
|
||||
<label class="control-label" for="HistoryEdit_Statistics">Statistics</label>
|
||||
<div class="controls">
|
||||
<table class="table table-striped table-bordered data-statistics">
|
||||
<tbody id="HistoryEdit_Statistics">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="btn-group dropup pull-left" id="HistoryEdit_DeleteGroup">
|
||||
<a class="btn dropdown-toggle btn-danger" data-toggle="dropdown"><i class="icon-trash-white"></i> Delete <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu confirm-menu">
|
||||
<li class="menu-header">Confirm</li>
|
||||
<li><a href="#" id="HistoryEdit_Delete">Yes, Delete</a></li>
|
||||
</ul>
|
||||
<div class="btn-group pull-left" id="HistoryEdit_DeleteGroup">
|
||||
<a href="#" class="btn pull-left" id="HistoryEdit_Delete"><i class="icon-trash"></i> Delete</a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group dropup pull-left" id="HistoryEdit_ReprocessGroup">
|
||||
@@ -1095,16 +1039,15 @@
|
||||
</div>
|
||||
|
||||
<div class="btn-group dropup pull-left" id="HistoryEdit_ReturnGroup">
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown">Return <span class="caret"></span></a>
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown">Return to Queue <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu confirm-menu">
|
||||
<li class="menu-header">Confirm</li>
|
||||
<li><a href="#" id="HistoryEdit_Return">Yes, Return to Queue</a></li>
|
||||
<li><a href="#" id="HistoryEdit_Return">Yes, Return</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="dialog-transmit" style="position:absolute;margin-left:320px;" id="HistoryEdit_Transmit"><img src="img/transmit.gif"></div>
|
||||
<a href="#" class="btn" data-dismiss="modal" id="HistoryEdit_Close">Close</a>
|
||||
<a href="#" class="btn btn-primary" id="HistoryEdit_Save">Save changes</a>
|
||||
<div class="dialog-transmit" style="position:absolute;margin-left:400px;" id="HistoryEdit_Transmit"><img src="img/transmit.gif"></div>
|
||||
<a href="#" class="btn btn-primary" data-dismiss="modal">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1134,13 +1077,8 @@
|
||||
<p>
|
||||
Delete selected downloads?
|
||||
</p>
|
||||
<p id="DownloadsDeleteConfirmDialog_Remain" class="confirm-help-block">
|
||||
Selected items will be removed from queue. Already downloaded files remain on disk (this behavior can be changed via option
|
||||
<strong><em>DeleteCleanupDisk</em></strong>).
|
||||
</p>
|
||||
<p id="DownloadsDeleteConfirmDialog_Cleanup" class="confirm-help-block">
|
||||
Selected items will be removed from queue. Already downloaded files will be deleted from disk (this behavior can be changed via option
|
||||
<strong><em>DeleteCleanupDisk</em></strong>).
|
||||
<p class="confirm-help-block">
|
||||
Selected items will be removed from the queue. Already downloaded files remain on disk.
|
||||
</p>
|
||||
</div>
|
||||
<div id="DownloadsDeleteConfirmDialog_OK">Delete</div>
|
||||
@@ -1227,7 +1165,7 @@
|
||||
<label class="control-label" for="URL">Add local files</label>
|
||||
<div class="controls">
|
||||
<div style="margin-top:6px; margin-bottom:10px;"><a href="#" class="btn" style="margin-top: -6px;" id="AddDialog_Select">Select files</a> or drop files here.</div>
|
||||
<input multiple="multiple" type="file" id="AddDialog_Input" class="hidden-file-input">
|
||||
<input multiple="multiple" type="file" id="AddDialog_Input">
|
||||
<p class="help-block" id="AddDialog_FilesHelp">You need a modern browser for this to work.</p>
|
||||
<div class="dialog-add-files hide" id="AddDialog_Files"></div>
|
||||
</div>
|
||||
@@ -1303,91 +1241,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- *** CHOOSE SCRIPT DIALOG ****************************************************** -->
|
||||
|
||||
<div class="modal modal-padded hide" id="ScriptListDialog">
|
||||
<div class="modal-header">
|
||||
<a class="close" href='#' data-dismiss="modal"><i class="icon-close"></i></a>
|
||||
<h3 id="ScriptListDialog_Title">Choose scripts</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body" style="padding-bottom:0px">
|
||||
<div class="form-vertical">
|
||||
<fieldset>
|
||||
|
||||
<p id="ScriptListDialog_Instruction">Select scripts for option <strong>DefScript</strong></p>
|
||||
|
||||
<div>
|
||||
<table class="table table-striped table-bordered table-check table-cancheck order-mode datatable" id="ScriptListDialog_ScriptTable" style="margin-bottom:15px;">
|
||||
<thead><tr><th><div class="check img-check"/></th><th>Name</th></tr></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p id="ScriptListDialog_OrderInfo" class="hide" style="margin-top:-5px; margin-bottom:10px;">The script execution order is saved globally in the option <em><strong>ScriptOrder</strong></em> and affects all
|
||||
categories as well as the order of scripts in the edit download dialog.</p>
|
||||
|
||||
<div class="hide" id="ScriptListDialog_ScriptTable_pager"></div>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn" data-dismiss="modal">Close</a>
|
||||
<a href="#" class="btn btn-primary" id="ScriptListDialog_Save">Save</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- *** RESTORE SETTINGS DIALOG ****************************************************** -->
|
||||
|
||||
<div class="modal modal-padded hide" id="RestoreSettingsDialog">
|
||||
<div class="modal-header">
|
||||
<a class="close" href='#' data-dismiss="modal"><i class="icon-close"></i></a>
|
||||
<h3>Restore Settings</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body" style="padding-bottom:0px">
|
||||
<div class="form-vertical">
|
||||
<fieldset>
|
||||
|
||||
<p id="RestoreSettingsDialog_Instruction">Select sections to restore. Tip: click on the checkbox of the table header to select all sections.</p>
|
||||
|
||||
<div>
|
||||
<table class="table table-striped table-bordered table-check table-cancheck datatable" id="RestoreSettingsDialog_SectionTable" style="margin-bottom:15px;">
|
||||
<thead><tr><th><div class="check img-check"/></th><th>Section</th></tr></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="hide" id="RestoreSettingsDialog_SectionTable_pager"></div>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn" data-dismiss="modal">Close</a>
|
||||
<a href="#" class="btn btn-primary" id="RestoreSettingsDialog_Restore">Restore</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- *** SETTINGS RESTORED DIALOG ************************************************** -->
|
||||
|
||||
<div class="modal modal-mini modal-center hide" id="SettingsRestoredDialog">
|
||||
<div class="modal-header">
|
||||
<a class="close" href='#' data-dismiss="modal"><i class="icon-close"></i></a>
|
||||
<h3>Settings restored</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Settings have been loaded from backup file.</p>
|
||||
<p>You can review the loaded settings and then save them by clicking on <em><strong>Save all changes</strong></em>.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn btn-primary" data-dismiss="modal">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- *** QUICK HELP: New Configuration Option ************************************************** -->
|
||||
|
||||
<div class="modal modal-mini modal-center hide" id="ConfigNewOptionHelp">
|
||||
@@ -1487,18 +1340,6 @@
|
||||
<strong>Merged</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Downloads_Splitted" data-duration="1000" class="alert alert-inverse alert-center alert-center-small hide">
|
||||
<strong>Splitted</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Downloads_SplitError" data-duration="2000" class="alert alert-error alert-center alert-center-medium hide">
|
||||
<strong>Could not split. Check messages for errors.</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Downloads_SplitNotPossible" data-duration="4000" class="alert alert-error alert-center alert-center-medium hide">
|
||||
<strong>Cannot split. Some of selected files are already (partially) downloaded.</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Downloads_Select" data-duration="2000" class="alert alert-error alert-center alert-center-small hide">
|
||||
<strong>Please select records first</strong>
|
||||
</div>
|
||||
@@ -1535,10 +1376,6 @@
|
||||
<strong>Post-Processing</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_History_Saved" data-duration="1000" class="alert alert-inverse alert-center alert-center-small hide">
|
||||
<strong>Saved</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Config_Unchanged" data-duration="2000" class="alert alert-inverse alert-center alert-center-small hide">
|
||||
<strong>Nothing to save</strong><br>No changes have been made
|
||||
</div>
|
||||
@@ -1552,14 +1389,6 @@
|
||||
Please wait few seconds, then refresh the page.
|
||||
</div>
|
||||
|
||||
<div id="Notif_Config_RestoreSections" data-duration="2000" class="alert alert-error alert-center alert-center-medium hide">
|
||||
<strong>Please select at least one section</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Config_Restoring" class="alert alert-inverse alert-center alert-center-small hide">
|
||||
<strong>Restoring settings...</strong>
|
||||
</div>
|
||||
|
||||
<div id="Notif_Debug" data-duration="400" class="alert alert-inverse alert-center alert-center-small hide">
|
||||
<strong>Debug</strong>
|
||||
</div>
|
||||
|
||||
117
webui/index.js
117
webui/index.js
@@ -26,10 +26,11 @@
|
||||
* In this module:
|
||||
* 1) Web-interface intialization;
|
||||
* 2) Web-interface settings;
|
||||
* 3) Refresh handling;
|
||||
* 4) Window resize handling including automatic theme switching (desktop/phone);
|
||||
* 5) Confirmation dialog;
|
||||
* 6) Popup notifications.
|
||||
* 3) RPC queue;
|
||||
* 4) Refresh handling;
|
||||
* 5) Window resize handling including automatic theme switching (desktop/phone);
|
||||
* 6) Confirmation dialog;
|
||||
* 7) Popup notifications.
|
||||
*/
|
||||
|
||||
/*** WEB-INTERFACE SETTINGS (THIS IS NOT NZBGET CONFIG!) ***********************************/
|
||||
@@ -64,10 +65,6 @@ var UISettings = (new function($)
|
||||
// The choosen interval is saved in web-browser and then restored.
|
||||
// The default value sets the interval on first use only.
|
||||
this.refreshInterval = 1;
|
||||
|
||||
// Number of refresh attempts if a communication error occurs.
|
||||
// If all attempts fail, an error is displayed and the automatic refresh stops.
|
||||
this.refreshRetries = 4;
|
||||
|
||||
// URL for communication with NZBGet via JSON-RPC
|
||||
this.rpcUrl = './jsonrpc';
|
||||
@@ -143,7 +140,7 @@ var Frontend = (new function($)
|
||||
$('#FirstUpdateInfo').show();
|
||||
|
||||
UISettings.load();
|
||||
Refresher.init();
|
||||
RPCController.init();
|
||||
|
||||
initControls();
|
||||
switchTheme();
|
||||
@@ -152,26 +149,26 @@ var Frontend = (new function($)
|
||||
Options.init();
|
||||
Status.init();
|
||||
Downloads.init({ updateTabInfo: updateTabInfo });
|
||||
DownloadsEditDialog.init();
|
||||
DownloadsMultiDialog.init();
|
||||
DownloadsMergeDialog.init();
|
||||
Messages.init({ updateTabInfo: updateTabInfo });
|
||||
History.init({ updateTabInfo: updateTabInfo });
|
||||
Upload.init();
|
||||
Config.init({ updateTabInfo: updateTabInfo });
|
||||
ConfigBackupRestore.init();
|
||||
ConfirmDialog.init();
|
||||
ScriptListDialog.init();
|
||||
RestoreSettingsDialog.init();
|
||||
|
||||
DownloadsEditDialog.init();
|
||||
DownloadsMultiDialog.init();
|
||||
DownloadsMergeDialog.init();
|
||||
DownloadsSplitDialog.init();
|
||||
HistoryEditDialog.init();
|
||||
|
||||
Refresher.init(RPCController.refresh);
|
||||
|
||||
$(window).resize(windowResized);
|
||||
|
||||
initialized = true;
|
||||
|
||||
Refresher.update();
|
||||
|
||||
// DEBUG: activate config tab
|
||||
//$('#DownloadsTab').removeClass('fade').removeClass('in');
|
||||
//$('#ConfigTabLink').tab('show');
|
||||
}
|
||||
|
||||
function initControls()
|
||||
@@ -240,6 +237,8 @@ var Frontend = (new function($)
|
||||
windowResized();
|
||||
firstLoad = false;
|
||||
}
|
||||
|
||||
Refresher.refreshCompleted();
|
||||
}
|
||||
|
||||
function beforeTabShow(e)
|
||||
@@ -460,23 +459,15 @@ var Frontend = (new function($)
|
||||
}(jQuery));
|
||||
|
||||
|
||||
/*** REFRESH CONTROL *********************************************************/
|
||||
/*** RPC CONTROL *********************************************************/
|
||||
|
||||
var Refresher = (new function($)
|
||||
var RPCController = (new function($)
|
||||
{
|
||||
'use strict';
|
||||
|
||||
// State
|
||||
var loadQueue;
|
||||
var firstLoad = true;
|
||||
var secondsToUpdate = -1;
|
||||
var refreshTimer = 0;
|
||||
var indicatorTimer = 0;
|
||||
var indicatorFrame=0;
|
||||
var refreshPaused = 0;
|
||||
var refreshing = false;
|
||||
var refreshNeeded = false;
|
||||
var refreshErrors = 0;
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
@@ -484,17 +475,13 @@ var Refresher = (new function($)
|
||||
RPC.connectErrorMessage = 'Cannot establish connection to NZBGet.'
|
||||
RPC.defaultFailureCallback = rpcFailure;
|
||||
RPC.next = loadNext;
|
||||
|
||||
$('#RefreshMenu li a').click(refreshIntervalClick);
|
||||
$('#RefreshButton').click(refreshClick);
|
||||
updateRefreshMenu();
|
||||
}
|
||||
|
||||
function refresh()
|
||||
this.refresh = function()
|
||||
{
|
||||
UISettings.connectionError = false;
|
||||
$('#ErrorAlert').hide();
|
||||
refreshStarted();
|
||||
Refresher.refreshStarted();
|
||||
|
||||
loadQueue = new Array(
|
||||
function() { Options.update(); },
|
||||
@@ -524,44 +511,49 @@ var Refresher = (new function($)
|
||||
{
|
||||
firstLoad = false;
|
||||
Frontend.loadCompleted();
|
||||
refreshCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
function rpcFailure(res, result)
|
||||
function rpcFailure(res)
|
||||
{
|
||||
// If a communication error occurs during status refresh we retry:
|
||||
// first attempt is made immediately, other attempts are made after defined refresh interval
|
||||
if (refreshing && !(result && result.error))
|
||||
{
|
||||
refreshErrors = refreshErrors + 1;
|
||||
if (refreshErrors === 1 && refreshErrors <= UISettings.refreshRetries)
|
||||
{
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
else if (refreshErrors <= UISettings.refreshRetries)
|
||||
{
|
||||
$('#RefreshError').show();
|
||||
scheduleNextRefresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Refresher.pause();
|
||||
UISettings.connectionError = true;
|
||||
$('#FirstUpdateInfo').hide();
|
||||
$('#ErrorAlert-text').html(res);
|
||||
$('#ErrorAlert').show();
|
||||
$('#RefreshError').hide();
|
||||
if (Status.status)
|
||||
{
|
||||
// stop animations
|
||||
Status.redraw();
|
||||
}
|
||||
};
|
||||
}(jQuery));
|
||||
|
||||
function refreshStarted()
|
||||
|
||||
/*** REFRESH CONTROL *********************************************************/
|
||||
|
||||
var Refresher = (new function($)
|
||||
{
|
||||
'use strict';
|
||||
|
||||
// State
|
||||
var secondsToUpdate = -1;
|
||||
var refreshTimer = 0;
|
||||
var indicatorTimer = 0;
|
||||
var indicatorFrame=0;
|
||||
var refreshPaused = 0;
|
||||
var refreshing = false;
|
||||
var refreshNeeded = false;
|
||||
var refreshCallback;
|
||||
|
||||
this.init = function(refresh)
|
||||
{
|
||||
refreshCallback = refresh;
|
||||
$('#RefreshMenu li a').click(refreshIntervalClick);
|
||||
$('#RefreshButton').click(refreshClick);
|
||||
updateRefreshMenu();
|
||||
}
|
||||
|
||||
this.refreshStarted = function()
|
||||
{
|
||||
clearTimeout(refreshTimer);
|
||||
refreshPaused = 0;
|
||||
@@ -570,11 +562,9 @@ var Refresher = (new function($)
|
||||
refreshAnimationShow();
|
||||
}
|
||||
|
||||
function refreshCompleted()
|
||||
this.refreshCompleted = function()
|
||||
{
|
||||
refreshing = false;
|
||||
refreshErrors = 0;
|
||||
$('#RefreshError').hide();
|
||||
scheduleNextRefresh();
|
||||
}
|
||||
|
||||
@@ -611,8 +601,7 @@ var Refresher = (new function($)
|
||||
// force animation restart
|
||||
indicatorFrame = 0;
|
||||
}
|
||||
refreshErrors = 0;
|
||||
refresh();
|
||||
refreshCallback();
|
||||
}
|
||||
|
||||
function scheduleNextRefresh()
|
||||
@@ -636,7 +625,7 @@ var Refresher = (new function($)
|
||||
secondsToUpdate -= 0.1;
|
||||
if (secondsToUpdate <= 0)
|
||||
{
|
||||
refresh();
|
||||
refreshCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -674,7 +663,7 @@ var Refresher = (new function($)
|
||||
'transform': 'rotate(' + degree + 'deg)'
|
||||
});
|
||||
|
||||
if ((!refreshing && indicatorFrame === 0 && (UISettings.refreshInterval === 0 || UISettings.refreshInterval > 1 || !UISettings.refreshAnimation)) || UISettings.connectionError)
|
||||
if (!refreshing && indicatorFrame === 0 && (UISettings.refreshInterval === 0 || UISettings.refreshInterval > 1 || !UISettings.refreshAnimation) || UISettings.connectionError)
|
||||
{
|
||||
indicatorTimer = 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2012-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -554,10 +554,6 @@ body.navfixed.scrolled .navbar-fixed-top .navbar-inner {
|
||||
background-position: -400px -80px;
|
||||
}
|
||||
|
||||
.icon-split {
|
||||
background-position: -432px -80px;
|
||||
}
|
||||
|
||||
.img-checkmark {
|
||||
background-position: -432px -16px;
|
||||
}
|
||||
@@ -590,10 +586,6 @@ body.navfixed.scrolled .navbar-fixed-top .navbar-inner {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.controls .label-status {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
/* links in black color */
|
||||
.datatable a {
|
||||
color: #000000;
|
||||
@@ -674,8 +666,7 @@ form {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#DownloadsEdit_PostParamData,
|
||||
#HistoryEdit_PostParamData {
|
||||
#DownloadsEdit_PostParamData {
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
@@ -792,11 +783,6 @@ tr.checked td {
|
||||
background-color: #FFFFCC;
|
||||
}
|
||||
|
||||
table.table-hidecheck thead > tr > th:first-child,
|
||||
table.table-hidecheck tbody > tr > td:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checked .progress {
|
||||
background-color: #FFFFE1;
|
||||
}
|
||||
@@ -906,11 +892,7 @@ table.table-hidecheck tbody > tr > td:first-child {
|
||||
}
|
||||
|
||||
.modal .form-horizontal .control-group:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modal .form-horizontal .retain-margin .control-group:last-child {
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-horizontal .control-group-last {
|
||||
@@ -929,11 +911,6 @@ table.table-hidecheck tbody > tr > td:first-child {
|
||||
.modal .input-xlarge {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.modal.modal-padded .input-xxlarge {
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
/* END: override bootstrap styles for modals */
|
||||
|
||||
.modal-bottom-toolbar .btn {
|
||||
@@ -986,7 +963,7 @@ ul.help > li {
|
||||
}
|
||||
|
||||
/* Make "select files" native control invisible */
|
||||
.hidden-file-input {
|
||||
#AddDialog_Input {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@@ -1114,11 +1091,6 @@ ul.help > li {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#ConfigNav.nav-list.long-list a {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
#ConfigNav.nav-list > .active > a,
|
||||
#ConfigNav.nav-list > .active > a:hover {
|
||||
color: #ffffff;
|
||||
@@ -1156,7 +1128,7 @@ ul.help > li {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
span.help-option-title {
|
||||
#ConfigContent span.help-option-title {
|
||||
color: #8D1212;
|
||||
}
|
||||
|
||||
@@ -1185,19 +1157,6 @@ span.help-option-title {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#ConfigContent table.editor {
|
||||
width: 97%;
|
||||
}
|
||||
|
||||
#ConfigContent table.editor td:first-child {
|
||||
width: 100%;
|
||||
padding-right:15px;
|
||||
}
|
||||
|
||||
#ConfigContent table.editor input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ConfigFooter hr {
|
||||
margin: 6px 0 15px;
|
||||
}
|
||||
@@ -1228,8 +1187,6 @@ div.ConfigFooter {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#DownloadsEdit_ParamTab div.control-group.wants-divider,
|
||||
#HistoryEdit_ParamTab div.control-group.wants-divider,
|
||||
#ConfigContent div.control-group,
|
||||
#ConfigContent.search div.control-group.multiset {
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
@@ -1250,6 +1207,7 @@ div.ConfigFooter {
|
||||
|
||||
#ConfigContent .control-label {
|
||||
width: 170px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#ConfigContent .form-horizontal .controls {
|
||||
@@ -1293,37 +1251,11 @@ div.ConfigFooter {
|
||||
color: #005580;
|
||||
}
|
||||
|
||||
#ScriptListDialog_ScriptTable td:nth-child(2) {
|
||||
padding-right: 100px;
|
||||
/* table "LIST OF ALL OPTIONS" */
|
||||
#ConfigContent .datatable td:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#ScriptListDialog_ScriptTable .btn-row-order-block {
|
||||
float: right;
|
||||
width: 100px;
|
||||
margin-right: -115px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#ScriptListDialog_ScriptTable .btn-row-order {
|
||||
float: none;
|
||||
width: 20px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#ScriptListDialog_ScriptTable tr:hover .btn-row-order {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#ScriptListDialog_ScriptTable tbody > tr:first-child div.btn-row-order:first-child,
|
||||
#ScriptListDialog_ScriptTable tbody > tr:last-child div.btn-row-order:last-child,
|
||||
#ScriptListDialog_ScriptTable tbody > tr:first-child div.btn-row-order:nth-child(2),
|
||||
#ScriptListDialog_ScriptTable tbody > tr:last-child div.btn-row-order:nth-child(3) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
/*#ScriptListDialog_ScriptTable*/
|
||||
|
||||
/****************************************************************************/
|
||||
/* SMARTPHONE THEME */
|
||||
|
||||
@@ -1404,10 +1336,6 @@ body.phone,
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.phone .controls .label-status {
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.phone .menu-header {
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
@@ -1789,8 +1717,7 @@ body.phone,
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.phone .modal-mini .modal-body,
|
||||
.phone .modal-padded .modal-body {
|
||||
.phone .modal-mini .modal-body {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
@@ -1878,8 +1805,6 @@ body.phone,
|
||||
}
|
||||
|
||||
.modal .input-xlarge ,
|
||||
.modal .input-xxlarge,
|
||||
.modal.modal-padded .input-xxlarge,
|
||||
.uneditable-mulitline-input {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
@@ -195,9 +195,8 @@ var Upload = (new function($)
|
||||
for (var i = 0; i<selectedFiles.length; i++)
|
||||
{
|
||||
var file = selectedFiles[i];
|
||||
var filename = file.name.replace(/\.queued$/g, '');
|
||||
var html = '<table><tr><td width="18px" valign="top"><i class="icon-file" style="vertical-align:top;margin-top:2px;"></i><img class="hide" style="vertical-align:top;margin-top:1px;" src="img/transmit-file.gif" width="16px" height="16px"></td><td>' +
|
||||
Util.formatNZBName(filename) + '</td></tr></table>';
|
||||
Util.formatNZBName(file.name) + '</td></tr></table>';
|
||||
$('#AddDialog_Files').append(html);
|
||||
files.push(file);
|
||||
}
|
||||
@@ -327,8 +326,7 @@ var Upload = (new function($)
|
||||
}
|
||||
var category = $('#AddDialog_Category').val();
|
||||
var priority = parseInt($('#AddDialog_Priority').val());
|
||||
var filename = file.name.replace(/\.queued$/g, '');
|
||||
RPC.call('append', [filename, category, priority, false, base64str], fileCompleted, fileFailure);
|
||||
RPC.call('append', [file.name, category, priority, false, base64str], fileCompleted, fileFailure);
|
||||
};
|
||||
|
||||
if (reader.readAsBinaryString)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2012-2013 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -261,7 +261,7 @@ var TabDialog = (new function($)
|
||||
var dialog = this;
|
||||
var sign = options.back ? -1 : 1;
|
||||
var fullscreen = options.fullscreen && !options.back;
|
||||
var bodyPadding = 15;
|
||||
var bodyPadding = 30;
|
||||
var dialogMargin = options.mini ? 0 : 15;
|
||||
var dialogBorder = 2;
|
||||
|
||||
@@ -292,8 +292,8 @@ var TabDialog = (new function($)
|
||||
// CONTROL POINT: at this point the destination dialog size is active
|
||||
// store destination positions and sizes
|
||||
|
||||
var newBodyHeight = fullscreen ? windowHeight - header.outerHeight() - footer.outerHeight() - dialogMargin*2 - bodyPadding*2 : body.height();
|
||||
var newTabWidth = fullscreen ? windowWidth - dialogMargin*2 - dialogBorder - bodyPadding*2 : toTab.width();
|
||||
var newBodyHeight = fullscreen ? windowHeight - header.outerHeight() - footer.outerHeight() - dialogMargin*2 - bodyPadding : body.height();
|
||||
var newTabWidth = fullscreen ? windowWidth - dialogMargin*2 - dialogBorder - bodyPadding : toTab.width();
|
||||
var leftPos = toTab.position().left;
|
||||
var newDialogPosition = dialog.position();
|
||||
var newDialogWidth = dialog.width();
|
||||
@@ -313,9 +313,9 @@ var TabDialog = (new function($)
|
||||
|
||||
body.css({position: '', height: oldBodyHeight});
|
||||
dialog.css('overflow', 'hidden');
|
||||
fromTab.css({position: 'absolute', left: leftPos, width: oldTabWidth, height: oldBodyHeight});
|
||||
toTab.css({position: 'absolute', width: newTabWidth, height: oldBodyHeight,
|
||||
left: sign * ((options.back ? newTabWidth : oldTabWidth) + bodyPadding*2)});
|
||||
fromTab.css({position: 'absolute', left: leftPos, width: oldTabWidth});
|
||||
toTab.css({position: 'absolute', width: newTabWidth, height: newBodyHeight,
|
||||
left: sign * ((options.back ? newTabWidth : oldTabWidth) + bodyPadding)});
|
||||
fromTab.show();
|
||||
|
||||
// animate dialog to destination position and sizes
|
||||
@@ -356,9 +356,8 @@ var TabDialog = (new function($)
|
||||
body.animate({height: newBodyHeight}, duration);
|
||||
}
|
||||
|
||||
fromTab.animate({left: sign * -((options.back ? newTabWidth : oldTabWidth) + bodyPadding*2),
|
||||
height: newBodyHeight + bodyPadding}, duration);
|
||||
toTab.animate({left: leftPos, height: newBodyHeight + bodyPadding}, duration, function()
|
||||
fromTab.animate({left: sign * -((options.back ? newTabWidth : oldTabWidth) + bodyPadding)}, duration);
|
||||
toTab.animate({left: leftPos}, duration, function()
|
||||
{
|
||||
fromTab.hide();
|
||||
fromTab.css({position: '', width: '', height: '', left: ''});
|
||||
@@ -405,7 +404,7 @@ var RPC = (new function($)
|
||||
var _this = this;
|
||||
|
||||
var request = JSON.stringify({nocache: new Date().getTime(), method: method, params: params});
|
||||
var xhr = new XMLHttpRequest();
|
||||
var xhr = createXMLHttpRequest();
|
||||
|
||||
xhr.open('post', this.rpcUrl);
|
||||
|
||||
@@ -472,4 +471,40 @@ var RPC = (new function($)
|
||||
};
|
||||
xhr.send(request);
|
||||
}
|
||||
|
||||
function createXMLHttpRequest()
|
||||
{
|
||||
var xmlHttp;
|
||||
|
||||
if (window.XMLHttpRequest)
|
||||
{
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
}
|
||||
else if (window.ActiveXObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
try
|
||||
{
|
||||
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xmlHttp==null)
|
||||
{
|
||||
alert("Your browser does not support XMLHTTP.");
|
||||
throw("Your browser does not support XMLHTTP.");
|
||||
}
|
||||
|
||||
return xmlHttp;
|
||||
}
|
||||
}(jQuery));
|
||||
|
||||
Reference in New Issue
Block a user